On Tue, Sep 14, 2021 at 7:39 AM Matthew John Cheetham via GitGitGadget <gitgitgadget@xxxxxxxxx> wrote: > > From: Matthew John Cheetham <mjcheetham@xxxxxxxxxxx> > > Delete an enlistment by first unregistering the repository and then > deleting the enlistment directory (usually the directory containing the > worktree `src/` directory). > > On Windows, if the current directory is inside the enlistment's > directory, change to the parent of the enlistment directory, to allow us > to delete the enlistment (directories used by processes e.g. as current > working directories cannot be deleted on Windows). But if the current directory is inside the enlistment's directory, didn't that happen because the parent process' current directory was inside the enlistment directory? Or was there some kind of directory switching that scalar itself was doing causing it to be inside the enlistment directory? If the the current directory was inside the enlistment's directory because it inherited a parent process' current directory, wouldn't that also prevent deleting it? If so, should there be a special check for that case and pre-emptively returning an error rather than attempting the recursive directory deletion and just spitting out an error when it fails? (Also seems slightly related to https://github.com/gitgitgadget/git/pull/1037, which I'll submit as soon as en/removing_untracked_fixes hits next.) > > Co-authored-by: Victoria Dye <vdye@xxxxxxxxxx> > Signed-off-by: Matthew John Cheetham <mjcheetham@xxxxxxxxxxx> > Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> > --- > contrib/scalar/scalar.c | 55 ++++++++++++++++++++++++++++++++ > contrib/scalar/scalar.txt | 8 +++++ > contrib/scalar/t/t9099-scalar.sh | 9 ++++++ > 3 files changed, 72 insertions(+) > > diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c > index 67fa5305225..00bedb0bf66 100644 > --- a/contrib/scalar/scalar.c > +++ b/contrib/scalar/scalar.c > @@ -8,6 +8,7 @@ > #include "config.h" > #include "run-command.h" > #include "refs.h" > +#include "dir.h" > > /* > * Remove the deepest subdirectory in the provided path string. Path must not > @@ -334,6 +335,33 @@ static char *remote_default_branch(const char *url) > return NULL; > } > > +static int delete_enlistment(struct strbuf *enlistment) > +{ > +#ifdef WIN32 > + struct strbuf parent = STRBUF_INIT; > +#endif > + > + if (unregister_dir()) > + die(_("failed to unregister repository")); > + > +#ifdef WIN32 > + /* > + * Change the current directory to one outside of the enlistment so > + * that we may delete everything underneath it. > + */ > + strbuf_addbuf(&parent, enlistment); > + strbuf_parent_directory(&parent); > + if (chdir(parent.buf) < 0) > + die_errno(_("could not switch to '%s'"), parent.buf); > + strbuf_release(&parent); > +#endif > + > + if (remove_dir_recursively(enlistment, 0)) > + die(_("failed to delete enlistment directory")); > + > + return 0; > +} > + > static int cmd_clone(int argc, const char **argv) > { > const char *branch = NULL; > @@ -694,6 +722,32 @@ static int cmd_unregister(int argc, const char **argv) > return unregister_dir(); > } > > +static int cmd_delete(int argc, const char **argv) > +{ > + struct option options[] = { > + OPT_END(), > + }; > + const char * const usage[] = { > + N_("scalar delete <enlistment>"), > + NULL > + }; > + struct strbuf enlistment = STRBUF_INIT; > + int res = 0; > + > + argc = parse_options(argc, argv, NULL, options, > + usage, 0); > + > + if (argc != 1) > + usage_with_options(usage, options); > + > + setup_enlistment_directory(argc, argv, usage, options, &enlistment); > + > + res = delete_enlistment(&enlistment); > + strbuf_release(&enlistment); > + > + return res; > +} > + > static struct { > const char *name; > int (*fn)(int, const char **); > @@ -704,6 +758,7 @@ static struct { > { "unregister", cmd_unregister }, > { "run", cmd_run }, > { "reconfigure", cmd_reconfigure }, > + { "delete", cmd_delete }, > { NULL, NULL}, > }; > > diff --git a/contrib/scalar/scalar.txt b/contrib/scalar/scalar.txt > index 2fa96fcabc6..6fc57707718 100644 > --- a/contrib/scalar/scalar.txt > +++ b/contrib/scalar/scalar.txt > @@ -14,6 +14,7 @@ scalar register [<enlistment>] > scalar unregister [<enlistment>] > scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>] > scalar reconfigure [ --all | <enlistment> ] > +scalar delete <enlistment> > > DESCRIPTION > ----------- > @@ -127,6 +128,13 @@ reconfigure the enlistment. > With the `--all` option, all enlistments currently registered with Scalar > will be reconfigured. Use this option after each Scalar upgrade. > > +Delete > +~~~~~~ > + > +delete <enlistment>:: > + This subcommand lets you delete an existing Scalar enlistment from your > + local file system, unregistering the repository. > + > SEE ALSO > -------- > linkgit:git-clone[1], linkgit:git-maintenance[1]. > diff --git a/contrib/scalar/t/t9099-scalar.sh b/contrib/scalar/t/t9099-scalar.sh > index 5fe7fabd0e5..7e8771d0eff 100755 > --- a/contrib/scalar/t/t9099-scalar.sh > +++ b/contrib/scalar/t/t9099-scalar.sh > @@ -76,4 +76,13 @@ test_expect_success 'scalar reconfigure' ' > test true = "$(git -C one/src config core.preloadIndex)" > ' > > +test_expect_success 'scalar delete without enlistment shows a usage' ' > + test_expect_code 129 scalar delete > +' > + > +test_expect_success 'scalar delete with enlistment' ' > + scalar delete cloned && > + test_path_is_missing cloned > +' > + > test_done > -- > gitgitgadget