The traditional way of updating sparse checkout is to open $GIT_DIR/info/sparse-checkout manually, edit it, save, then run "git checkout" or "git read-tree -m -u HEAD". That's not convenient. "git checkout -S" is introduced to combine those steps in one. It also provides some additional checks: - warn users if core.sparseCheckout is off - refuse to update sparse checkout if there is no valid sparse patterns (faulty sparse-checkout file for example) Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- Documentation/git-checkout.txt | 16 +++++++++++++ builtin/checkout.c | 42 +++++++++++++++++++++++++++++++++- t/t1011-read-tree-sparse-checkout.sh | 18 ++++++++++++++ templates/info--sparse-checkout | 1 + 4 files changed, 76 insertions(+), 1 deletions(-) diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 22d3611..478bfe7 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -12,6 +12,7 @@ SYNOPSIS 'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>] 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>... 'git checkout' --patch [<tree-ish>] [--] [<paths>...] +'git checkout' -S DESCRIPTION ----------- @@ -176,6 +177,13 @@ the conflicted merge in the specified paths. This means that you can use `git checkout -p` to selectively discard edits from your current working tree. +-S:: +--update-sparse-checkout:: + An editor is invoked to let you update your sparse checkout + patterns. The updated patterns will be saved in + $GIT_DIR/info/sparse-checkout. The working directory is also + updated. An empty file will abort the process. + <branch>:: Branch to checkout; if it refers to a branch (i.e., a name that, when prepended with "refs/heads/", is a valid ref), then that @@ -316,6 +324,14 @@ $ git add frotz ------------ +ENVIRONMENT AND CONFIGURATION VARIABLES +--------------------------------------- +The editor used to edit the commit log message will be chosen from the +GIT_EDITOR environment variable, the core.editor configuration variable, the +VISUAL environment variable, or the EDITOR environment variable (in that +order). See linkgit:git-var[1] for details. + + Author ------ Written by Linus Torvalds <torvalds@xxxxxxxx> diff --git a/builtin/checkout.c b/builtin/checkout.c index 9240faf..47847b3 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -675,6 +675,31 @@ static const char *unique_tracking_name(const char *name) return NULL; } +static void edit_info_sparse_checkout() +{ + char *tmpfile = xstrdup(git_path("sparse-checkout")); + struct exclude_list el; + int i; + + copy_file(tmpfile, git_path("info/sparse-checkout"), 0666); + + if (launch_editor(tmpfile, NULL, NULL)) + exit(1); + + memset(&el, 0, sizeof(el)); + if (add_excludes_from_file_to_list(tmpfile, "", 0, NULL, &el, 0) < 0 || + el.nr == 0) + die("No valid sparse patterns. Abort."); + for (i = 0; i < el.nr; i++) + free(el.excludes[i]); + free(el.excludes); + + if (rename(tmpfile, git_path("info/sparse-checkout")) < 0) + die_errno("Can't update %s", git_path("info/sparse-checkout")); + + free(tmpfile); +} + int cmd_checkout(int argc, const char **argv, const char *prefix) { struct checkout_opts opts; @@ -685,6 +710,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) char *conflict_style = NULL; int patch_mode = 0; int dwim_new_local_branch = 1; + int update_sparse_checkout = 0; struct option options[] = { OPT__QUIET(&opts.quiet), OPT_STRING('b', NULL, &opts.new_branch, "branch", @@ -704,6 +730,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_STRING(0, "conflict", &conflict_style, "style", "conflict style (merge or diff3)"), OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"), + OPT_BOOLEAN('S', "update-sparse-checkout", &update_sparse_checkout, + "open up editor to edit $GIT_DIR/info/sparse-checkout" ), { OPTION_BOOLEAN, 0, "guess", &dwim_new_local_branch, NULL, "second guess 'git checkout no-such-branch'", PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, @@ -722,6 +750,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); + if (update_sparse_checkout && !core_apply_sparse_checkout) + die("core.sparseCheckout needs to be turned on"); + /* we can assume from now on new_branch = !new_branch_force */ if (opts.new_branch && opts.new_branch_force) die("-B cannot be used with -b"); @@ -874,6 +905,9 @@ no_reference: if (!pathspec) die("invalid path specification"); + if (update_sparse_checkout) + die("git checkout: update paths is incompatible with updating sparse checkout."); + if (patch_mode) return interactive_checkout(new.name, pathspec, &opts); @@ -892,8 +926,11 @@ no_reference: return checkout_paths(source_tree, pathspec, &opts); } - if (patch_mode) + if (patch_mode) { + if (update_sparse_checkout) + die("git checkout: interactive checkout is incompatible with updating sparse checkout."); return interactive_checkout(new.name, NULL, &opts); + } if (opts.new_branch) { struct strbuf buf = STRBUF_INIT; @@ -915,5 +952,8 @@ no_reference: if (opts.writeout_stage) die("--ours/--theirs is incompatible with switching branches."); + if (update_sparse_checkout) + edit_info_sparse_checkout(); + return switch_branches(&opts, &new); } diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 50f7dfe..fe4716c 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -184,4 +184,22 @@ test_expect_success 'read-tree --reset removes outside worktree' ' test_cmp empty result ' +test_expect_success 'git checkout -S fails to launch editor' ' + GIT_EDITOR=/non-existent test_must_fail git checkout -S && + grep init.t .git/info/sparse-checkout +' + +test_expect_success 'git checkout -S' ' + git checkout -f top && + cat >editor.sh <<\EOF && +#!/bin/sh +echo sub > "$1" +EOF + chmod 755 editor.sh && + GIT_EDITOR="./editor.sh" git checkout -S && + grep sub .git/info/sparse-checkout && + test -f sub/added && + test ! -f init.t +' + test_done diff --git a/templates/info--sparse-checkout b/templates/info--sparse-checkout index 7426475..588008b 100644 --- a/templates/info--sparse-checkout +++ b/templates/info--sparse-checkout @@ -1,3 +1,4 @@ # Specify what files are checked out in working directory # Run "git checkout" after updating this file to update working directory +# If this is opened by "git checkout -S", empty this file will abort it. * -- 1.7.3.2.210.g045198 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html