From 72061b80a658657235afa628d9889ee6915e3dba Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:31:06 -0400 Subject: [PATCH 1/8] fixup! scalar register: set recommended config settings Fix to allow non- workdirs --- contrib/scalar/scalar.c | 98 ++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 31 deletions(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index e6f3f1687ad626..19a05e968526d3 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -19,55 +19,91 @@ static int is_unattended(void) { return git_env_bool("Scalar_UNATTENDED", 0); } +/* + * Remove the deepest subdirectory in the provided path string. Path must not + * include a trailing path separator. Returns 1 if parent directory found, + * otherwise 0. + */ +static int strbuf_parentdir(struct strbuf *buf) +{ + size_t len = buf->len; + size_t offset = offset_1st_component(buf->buf); + char *path_sep = find_last_dir_sep(buf->buf + offset); + strbuf_setlen(buf, path_sep ? path_sep - buf->buf : offset); + + return buf->len < len; +} + static void setup_enlistment_directory(int argc, const char **argv, const char * const *usagestr, - const struct option *options) + const struct option *options, + struct strbuf *enlistment_root) { + struct strbuf path = STRBUF_INIT; + char *root; + int enlistment_found = 0; + if (startup_info->have_repository) BUG("gitdir already set up?!?"); if (argc > 1) usage_with_options(usagestr, options); + /* find the worktree, determine its corresponding root */ if (argc == 1) { - char *src = xstrfmt("%s/src", argv[0]); - const char *dir = is_directory(src) ? src : argv[0]; + strbuf_add_absolute_path(&path, argv[0]); + } else if (strbuf_getcwd(&path) < 0) { + die(_("need a working directory")); + } - if (chdir(dir) < 0) - die_errno(_("could not switch to '%s'"), dir); + strbuf_trim_trailing_dir_sep(&path); + do { + const size_t len = path.len; - free(src); - } else { - /* find the worktree, and ensure that it is named `src` */ - struct strbuf path = STRBUF_INIT; + /* check if currently in enlistment root with src/ workdir */ + strbuf_addstr(&path, "/src/.git"); + if (is_git_directory(path.buf)) { + strbuf_strip_suffix(&path, "/.git"); - if (strbuf_getcwd(&path) < 0) - die(_("need a working directory")); - - for (;;) { - size_t len = path.len; - - strbuf_addstr(&path, "/src/.git"); - if (is_git_directory(path.buf)) { - strbuf_setlen(&path, len); - strbuf_addstr(&path, "/src"); - if (chdir(path.buf) < 0) - die_errno(_("could not switch to '%s'"), - path.buf); - strbuf_release(&path); - break; - } + if (enlistment_root) + strbuf_add(enlistment_root, path.buf, len); - while (len > 0 && !is_dir_sep(path.buf[--len])) - ; /* keep looking for parent directory */ + enlistment_found = 1; + break; + } - if (!len) - die(_("could not find enlistment root")); + /* reset to original path */ + strbuf_setlen(&path, len); + /* check if currently in workdir */ + strbuf_addstr(&path, "/.git"); + if (is_git_directory(path.buf)) { strbuf_setlen(&path, len); + + if (enlistment_root) { + /* + * If the worktree's directory's name is `src`, the enlistment is the + * parent directory, otherwise it is identical to the worktree. + */ + root = strip_path_suffix(path.buf, "src"); + strbuf_addstr(enlistment_root, root ? root : path.buf); + free(root); + } + + enlistment_found = 1; + break; } - } + strbuf_setlen(&path, len); + } while (strbuf_parentdir(&path)); + + if (!enlistment_found) + die(_("could not find enlistment root")); + + if (chdir(path.buf) < 0) + die_errno(_("could not switch to '%s'"), path.buf); + + strbuf_release(&path); setup_git_directory(); } @@ -1299,7 +1335,7 @@ static int cmd_register(int argc, const char **argv) argc = parse_options(argc, argv, NULL, options, usage, 0); - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, NULL); return register_dir(); } From 20597014cb622e1d9b41ec32ee504509bbfc5f2a Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:36:08 -0400 Subject: [PATCH 2/8] fixup! scalar register/unregister: start/stop maintenance on repository Add argument for register --- contrib/scalar/scalar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index 19a05e968526d3..1e063d00a4ae05 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1520,7 +1520,7 @@ static int cmd_unregister(int argc, const char **argv) strbuf_release(&path); } - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, NULL); return unregister_dir(); } From 419cbc55c34484925b2a9e1ae09034e8af161ac8 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:43:41 -0400 Subject: [PATCH 3/8] fixup! scalar unregister: handle deleted enlistment directory gracefully Improve handling of non-`src` workdirs in `scalar unregister` --- contrib/scalar/scalar.c | 49 +++++++++++++++++++++----------- contrib/scalar/t/t9099-scalar.sh | 35 +++++++++++++++++++++++ 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index 1e063d00a4ae05..b504fc4ceb2408 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1476,6 +1476,24 @@ static int cmd_run(int argc, const char **argv) return 0; } +static int remove_deleted_enlistment(struct strbuf *path) +{ + int res = 0; + strbuf_realpath_forgiving(path, path->buf, 1); + + if (run_git("config", "--global", + "--unset", "--fixed-value", + "scalar.repo", path->buf, NULL) < 0) + res = -1; + + if (run_git("config", "--global", + "--unset", "--fixed-value", + "maintenance.repo", path->buf, NULL) < 0) + res = -1; + + return res; +} + static int cmd_unregister(int argc, const char **argv) { struct option options[] = { @@ -1495,29 +1513,26 @@ static int cmd_unregister(int argc, const char **argv) * mistake and _still_ wants to unregister the thing. */ if (argc == 1) { - struct strbuf path = STRBUF_INIT; + struct strbuf src_path = STRBUF_INIT, workdir_path = STRBUF_INIT; - strbuf_addf(&path, "%s/src/.git", argv[0]); - if (!is_directory(path.buf)) { - int res = 0; + strbuf_addf(&src_path, "%s/src/.git", argv[0]); + strbuf_addf(&workdir_path, "%s/.git", argv[0]); + if (!is_directory(src_path.buf) && !is_directory(workdir_path.buf)) { + /* remove possible matching registrations */ + int res = -1; - strbuf_strip_suffix(&path, "/.git"); - strbuf_realpath_forgiving(&path, path.buf, 1); + strbuf_strip_suffix(&src_path, "/.git"); + res = remove_deleted_enlistment(&src_path) && res; - if (run_git("config", "--global", - "--unset", "--fixed-value", - "scalar.repo", path.buf, NULL) < 0) - res = -1; - - if (run_git("config", "--global", - "--unset", "--fixed-value", - "maintenance.repo", path.buf, NULL) < 0) - res = -1; + strbuf_strip_suffix(&workdir_path, "/.git"); + res = remove_deleted_enlistment(&workdir_path) && res; - strbuf_release(&path); + strbuf_release(&src_path); + strbuf_release(&workdir_path); return res; } - strbuf_release(&path); + strbuf_release(&src_path); + strbuf_release(&workdir_path); } setup_enlistment_directory(argc, argv, usage, options, NULL); diff --git a/contrib/scalar/t/t9099-scalar.sh b/contrib/scalar/t/t9099-scalar.sh index fd8d26324111b9..6037cb046c271c 100755 --- a/contrib/scalar/t/t9099-scalar.sh +++ b/contrib/scalar/t/t9099-scalar.sh @@ -204,4 +204,39 @@ test_expect_success '`scalar clone` with GVFS-enabled server' ' ) ' +test_expect_success '`scalar register` & `unregister` with existing repo' ' + git init existing && + scalar register existing && + git config --get --global --fixed-value \ + maintenance.repo "$(pwd)/existing" && + scalar list >scalar.repos && + grep -F "$(pwd)/existing" scalar.repos && + scalar unregister existing && + test_must_fail git config --get --global --fixed-value \ + maintenance.repo "$(pwd)/existing" && + scalar list >scalar.repos && + ! grep -F "$(pwd)/existing" scalar.repos +' + +test_expect_success '`scalar unregister` with existing repo, deleted .git' ' + scalar register existing && + rm -rf existing/.git && + scalar unregister existing && + test_must_fail git config --get --global --fixed-value \ + maintenance.repo "$(pwd)/existing" && + scalar list >scalar.repos && + ! grep -F "$(pwd)/existing" scalar.repos +' + +test_expect_success '`scalar register` existing repo with `src` folder' ' + git init existing && + mkdir -p existing/src && + scalar register existing/src && + scalar list >scalar.repos && + grep -F "$(pwd)/existing" scalar.repos && + scalar unregister existing && + scalar list >scalar.repos && + ! grep -F "$(pwd)/existing" scalar.repos +' + test_done From f05be53069bf54c24d9d9376fc1c5aff2d8d2992 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:46:47 -0400 Subject: [PATCH 4/8] fixup! scalar: implement the `run` command Add argument to `setup_enlistment_directory` for `scalar run` --- contrib/scalar/scalar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index b504fc4ceb2408..dace8cd9413f6b 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1457,7 +1457,7 @@ static int cmd_run(int argc, const char **argv) argc--; argv++; - setup_enlistment_directory(argc, argv, usagestr, options); + setup_enlistment_directory(argc, argv, usagestr, options, NULL); strbuf_release(&buf); if (i == 0) From f6ca26f1add2865be558d31e6b60c0f94791def2 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:48:53 -0400 Subject: [PATCH 5/8] fixup! scalar: allow reconfiguring an existing enlistment Add argument to `setup_enlistment_directory` for `scalar reconfigure` --- contrib/scalar/scalar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index dace8cd9413f6b..b4cd62ccf0d6ed 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1371,7 +1371,7 @@ static int cmd_reconfigure(int argc, const char **argv) usage, 0); if (!all) { - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, NULL); return set_recommended_config(1); } From b59e481058a6561d42fd4f0b4a17566859b0f0ef Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:51:16 -0400 Subject: [PATCH 6/8] fixup! Implement `scalar diagnose` Use explicit `enlistment_root` result for `scalar diagnose` --- contrib/scalar/scalar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index b4cd62ccf0d6ed..c757f3e12b48f5 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1221,9 +1221,9 @@ static int cmd_diagnose(int argc, const char **argv) argc = parse_options(argc, argv, NULL, options, usage, 0); - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, &buf); - strbuf_addstr(&buf, "../.scalarDiagnostics/scalar_"); + strbuf_addstr(&buf, "/.scalarDiagnostics/scalar_"); strbuf_addftime(&buf, "%Y%m%d_%H%M%S", localtime_r(&now, &tm), 0, 0); if (run_git("init", "-q", "-b", "dummy", "--bare", buf.buf, NULL)) { res = error(_("could not initialize temporary repository: %s"), From ea3e35852e2d67fe2dbb792c2a2c1d50d9eb0d1c Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:54:13 -0400 Subject: [PATCH 7/8] fixup! scalar: implement the `delete` command Improve non-`src` enlistment workdir handling for `scalar delete` --- contrib/scalar/scalar.c | 29 ++++++++++------------------- contrib/scalar/t/t9099-scalar.sh | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index c757f3e12b48f5..a24648ec2c0b7a 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -825,17 +825,8 @@ static char *remote_default_branch(const char *url) return NULL; } -static void strbuf_parentdir(struct strbuf *buf) +static int delete_enlistment(struct strbuf *enlistment) { - int len = buf->len; - while (len > 0 && !is_dir_sep(buf->buf[--len])) - ; /* keep looking for parent directory */ - strbuf_setlen(buf, len); -} - -static int delete_enlistment(void) -{ - struct strbuf enlistment = STRBUF_INIT; #ifdef WIN32 struct strbuf parent = STRBUF_INIT; #endif @@ -843,24 +834,19 @@ static int delete_enlistment(void) if (unregister_dir()) die(_("failed to unregister repository")); - /* Compute the enlistment path (parent of the worktree) */ - strbuf_addstr(&enlistment, the_repository->worktree); - strbuf_parentdir(&enlistment); - #ifdef WIN32 /* Change current directory to one outside of the enlistment so that we may delete everything underneath it. */ - strbuf_addbuf(&parent, &enlistment); + strbuf_addbuf(&parent, enlistment); strbuf_parentdir(&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)) + if (remove_dir_recursively(enlistment, 0)) die(_("failed to delete enlistment directory")); - strbuf_release(&enlistment); return 0; } @@ -1549,6 +1535,8 @@ static int cmd_delete(int argc, const char **argv) N_("scalar delete "), NULL }; + struct strbuf enlistment = STRBUF_INIT; + int res = 0; argc = parse_options(argc, argv, NULL, options, usage, 0); @@ -1556,9 +1544,12 @@ static int cmd_delete(int argc, const char **argv) if (argc != 1) usage_with_options(usage, options); - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, &enlistment); - return delete_enlistment(); + res = delete_enlistment(&enlistment); + strbuf_release(&enlistment); + + return res; } static int cmd_help(int argc, const char **argv) diff --git a/contrib/scalar/t/t9099-scalar.sh b/contrib/scalar/t/t9099-scalar.sh index 6037cb046c271c..9644f91a6cd6b7 100755 --- a/contrib/scalar/t/t9099-scalar.sh +++ b/contrib/scalar/t/t9099-scalar.sh @@ -204,6 +204,17 @@ test_expect_success '`scalar clone` with GVFS-enabled server' ' ) ' +test_expect_success '`scalar register` parallel to worktree' ' + git init test-repo/src && + mkdir -p test-repo/out && + scalar register test-repo/out && + git config --get --global --fixed-value \ + maintenance.repo "$(pwd)/test-repo/src" && + scalar list >scalar.repos && + grep -F "$(pwd)/test-repo/src" scalar.repos && + scalar delete test-repo +' + test_expect_success '`scalar register` & `unregister` with existing repo' ' git init existing && scalar register existing && @@ -239,4 +250,11 @@ test_expect_success '`scalar register` existing repo with `src` folder' ' ! grep -F "$(pwd)/existing" scalar.repos ' +test_expect_success '`scalar delete` with existing repo' ' + git init existing && + scalar register existing && + scalar delete existing && + test_path_is_missing existing +' + test_done From 1976a6ef20813a77bb817142115374447d22f0e8 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Tue, 3 Aug 2021 22:55:30 -0400 Subject: [PATCH 8/8] fixup! scalar: add the `cache-server` command Add extra argument to `setup_enlistment_directory` in `scalar cache-server` --- contrib/scalar/scalar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c index a24648ec2c0b7a..055937510be00e 100644 --- a/contrib/scalar/scalar.c +++ b/contrib/scalar/scalar.c @@ -1628,7 +1628,7 @@ static int cmd_cache_server(int argc, const char **argv) usage_msg_opt(_("--get/--set/--list are mutually exclusive"), usage, options); - setup_enlistment_directory(argc, argv, usage, options); + setup_enlistment_directory(argc, argv, usage, options, NULL); if (list) { const char *name = list, *url = list;