/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* Copyright 2013-2021 The Libfossil Authors, see LICENSES/BSD-2-Clause.txt SPDX-License-Identifier: BSD-2-Clause-FreeBSD SPDX-FileCopyrightText: 2021 The Libfossil Authors SPDX-ArtifactOfProjectName: Libfossil SPDX-FileType: Code Heavily indebted to the Fossil SCM project (https://fossil-scm.org). ***************************************************************************** This file is for testing the ability to "remove" files from a checkout. */ #include "libfossil.h" static struct { bool dryRun; bool unlink; short int verbose; unsigned int counter; fsl_buffer fname; } App = { false, false, 0, 0, fsl_buffer_empty_m }; static int fsl_ckout_unmanage_f_my(fsl_ckout_unmanage_state const * us){ f_out("UNMANAGED %s\n", us->filename); ++App.counter; if(App.unlink){ fsl_buffer_reuse(&App.fname); if(0==fsl_cx_stat2(us->f, false, us->filename, NULL, &App.fname, true)){ if(App.verbose){ if(App.dryRun){ f_out("Dry-run: not unlinking: %b\n", &App.fname); }else{ f_out("Unlinking: %b\n", &App.fname); } } if(!App.dryRun){ int const rc = fsl_file_unlink(fsl_buffer_cstr(&App.fname)); if(rc && App.verbose){ f_out("Unlink failed: %s: %b\n", fsl_rc_cstr(rc), &App.fname); } } } } return 0; } int main(int argc, char const * const * argv ){ int rc = 0; fsl_cx * f; bool inTrans = false; fsl_db * db; fsl_id_bag idBag = fsl_id_bag_empty; fcli_cliflag FCliFlags[] = { FCLI_FLAG_BOOL("n","dry-run", &App.dryRun,"Dry-run mode."), FCLI_FLAG_BOOL("u", "unlink", &App.unlink, "Unlink (delete) newly-unmanaged files. " "Will silently fail if the files cannot be " "deleted, e.g. due to access rights. The " "--verbose flag will cause it to report such " "cases but they do not cause the unmanagement " "to fail."), fcli_cliflag_empty_m }; fcli_help_info FCliHelp = { "Queues up files to be removed from future SCM history (unmanaged) " "at the next commit.", "file [...file]", NULL }; rc = fcli_setup_v2(argc, argv, FCliFlags, &FCliHelp); if(rc) goto end; f = fcli_cx(); db = fsl_cx_db_ckout(f); if(!db){ rc = fsl_cx_err_set(f, FSL_RC_NOT_A_CKOUT, "This app requires a checkout db."); goto end; } if(fcli_has_unused_flags(0)) goto end; else if(!fcli_next_arg(false)){ rc = fcli_err_set(FSL_RC_MISUSE,"No file names provided."); goto end; } fsl_buffer_reserve(&App.fname, 1024); rc = fsl_cx_transaction_begin(f); if(rc){ goto end; } inTrans = true; rc = fsl_vfile_changes_scan(f, 0, 0); if(rc) goto end; rc = fcli_args_to_vfile_ids(&idBag, 0, true, false); if(rc) goto end; fsl_ckout_unmanage_opt ropt = fsl_ckout_unmanage_opt_empty; ropt.scanForChanges = false; ropt.vfileIds = &idBag; ropt.relativeToCwd = true; ropt.callback = fsl_ckout_unmanage_f_my; App.verbose = fcli_is_verbose(); rc = fsl_ckout_unmanage(f, &ropt); if(rc) goto end; f_out("Total number of files rm'd: %u\n", App.counter); if(App.dryRun){ f_out("Dry-run mode. Rolling back transaction.\n"); fsl_cx_transaction_end(f, true); }else{ rc = fsl_cx_transaction_end(f, false); } inTrans = 0; end: fsl_buffer_clear(&App.fname); fsl_id_bag_clear(&idBag); if(inTrans){ fsl_cx_transaction_end(f, true); } return fcli_end_of_main(rc); }