All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 15/16] checkout: add new options to support narrow checkout
Date: Sun, 14 Sep 2008 20:08:04 +0700	[thread overview]
Message-ID: <1221397685-27715-16-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1221397685-27715-15-git-send-email-pclouds@gmail.com>

These options include:

 --full: return to full checkout (default)
 --path: narrow checkout to some areas according to given spec
 --add-path/--remove-path: adjust current narrow checkout

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-checkout.txt |   68 +++++++++++++++++++++++++++++++++-
 builtin-checkout.c             |   44 ++++++++++++++++++++++
 t/t2011-checkout-narrow.sh     |   80 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+), 2 deletions(-)
 create mode 100755 t/t2011-checkout-narrow.sh

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 82e154d..2ae483b 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -8,8 +8,10 @@ git-checkout - Checkout a branch or paths to the working tree
 SYNOPSIS
 --------
 [verse]
-'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
-'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
+'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m]
+	  [<narrow options>] [<branch>]
+'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>]
+	  [<narrow options>] [--] <paths>...
 
 DESCRIPTION
 -----------
@@ -34,6 +36,10 @@ used to specify a specific tree-ish (i.e. commit, tag or tree)
 to update the index for the given paths before updating the
 working tree.
 
+<narrow options> include --full, --path, --add-path and --remove-path.
+The last three require narrow spec. Please refer to "narrow checkout"
+section to have more information about this mode.
+
 The index may contain unmerged entries after a failed merge.  By
 default, if you try to check out such an entry from the index, the
 checkout operation will fail and nothing will be checked out.
@@ -108,6 +114,22 @@ exlicitly give a name with '-b' in such a case.
 	However, with this option, a three-way merge between the current
 	branch, your working tree contents, and the new branch
 	is done, and you will be on the new branch.
+
+--full::
+	Quit narrow checkout mode. Return to full checkout.
+
+--path=<narrow_spec>::
+	Re-apply new narrow spec on current working directory to
+	form new checkout area.
+
+--add-path=<narrow_spec>::
+	Checkout more areas specified by narrow spec to current
+	checkout area.
+
+--remove-path=<narrow_spec>::
+	Narrow checkout area by removing files specified by narrow spec
+	from current checkout area. This operation will fail if there
+	is unmerged or modified files in the removing areas.
 +
 When a merge conflict happens, the index entries for conflicting
 paths are left unmerged, and you need to resolve the conflicts
@@ -171,6 +193,48 @@ the reflog for HEAD where you were, e.g.
 $ git log -g -2 HEAD
 ------------
 
+Narrow checkout
+---------------
+
+Normally when you do checkout a branch, your working directory
+will be fully populated. In some situations, you just need to
+work on certain files, no full checkout is required. Narrow
+checkout is a mode that limits checkout area according to your
+rules.
+
+Because narrow checkout uses new index format, it will be
+incompatible with git prior to 1.6.0. In order to make your
+working directory work with those versions, you can use `git
+checkout --full` to return to normal mode (and compatible index
+format).
+
+Narrow works by applying your rules to the index, marking which
+file you need and which file you need not. Modified/Unmerged
+files cannot be marked unneeded. Unnecessary files will be
+removed from working directory.  Note that after this step,
+removed files can still be added to working directory when they
+are needed by any git command. For example, when you have a merge
+conflict, conflicted files will be checked out on working
+directory and will no longer be marked "unneeded".
+
+New files after merges will always be "needed". You can also
+apply rules when switching branches to avoid unwanted new files.
+
+Files that are marked "no-checkout" will be treated like entries
+with "assume-unchanged bit" (see linkgit:git-update-index[1]). In
+short, Git will never look for those files in working directory
+no matter whether they exist in working directory.
+
+You can apply your rules at once with --path option, or do it
+incrementally with --add-path and --remove-path.
+
+Narrow spec will be used to specify how you want to narrow your
+checkout. It is a list of pathspecs separated by colons. Each
+patchspec specifies what files should be checked out on working
+directory. Pathspec can contain wildcards and is relative to
+current working directory. Usually asterisk (*) does not match
+slashes. If a pathspec is prefixed by a plus sign (+), then
+any asterisk will match anything, even slashes.
 
 EXAMPLES
 --------
diff --git a/builtin-checkout.c b/builtin-checkout.c
index c7b0aad..b6bc3c5 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -33,6 +33,12 @@ struct checkout_opts {
 	const char *new_branch;
 	int new_branch_log;
 	enum branch_track track;
+
+	const char *prefix;
+	char *new_path;
+	char *add_path;
+	char *remove_path;
+	int no_narrow_checkout;
 };
 
 static int post_checkout_hook(struct commit *old, struct commit *new,
@@ -412,6 +418,24 @@ static int merge_working_tree(struct checkout_opts *opts,
 		tree = parse_tree_indirect(new->commit->object.sha1);
 		init_tree_desc(&trees[1], tree->buffer, tree->size);
 
+		topts.narrow_prefix = opts->prefix;
+		if (opts->no_narrow_checkout) {
+			/* leave narrow_spec NULL */
+			topts.new_narrow_path = 1;
+		}
+		else if (opts->new_path) {
+			topts.narrow_spec = opts->new_path;
+			topts.new_narrow_path = 1;
+		}
+		else if (opts->add_path) {
+			topts.narrow_spec = opts->add_path;
+			topts.add_narrow_path = 1;
+		}
+		else if (opts->remove_path) {
+			topts.narrow_spec = opts->remove_path;
+			topts.remove_narrow_path = 1;
+		}
+
 		ret = unpack_trees(2, trees, &topts);
 		if (ret == -1) {
 			/*
@@ -600,6 +624,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN('m', "merge", &opts.merge, "merge"),
 		OPT_STRING(0, "conflict", &conflict_style, "style",
 			   "conflict style (merge or diff3)"),
+		OPT_BOOLEAN(0, "full", &opts.no_narrow_checkout, "quit sparse checkout"),
+		OPT_STRING(0, "path", &opts.new_path, "prefixes", "apply new narrow checkout path"),
+		OPT_STRING(0, "add-path", &opts.add_path, "prefixes", "add more checkout area"),
+		OPT_STRING(0, "remove-path", &opts.remove_path, "prefixes", "narrow checkout area"),
 		OPT_END(),
 	};
 	int has_dash_dash;
@@ -610,6 +638,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	git_config(git_checkout_config, NULL);
 
 	opts.track = BRANCH_TRACK_UNSPECIFIED;
+	opts.prefix = prefix;
 
 	argc = parse_options(argc, argv, options, checkout_usage,
 			     PARSE_OPT_KEEP_DASHDASH);
@@ -639,6 +668,18 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	if (!opts.new_branch && (opts.track != git_branch_track))
 		die("git checkout: --track and --no-track require -b");
 
+	if (((opts.no_narrow_checkout ? 1 : 0) +
+	     (opts.new_path ? 1 : 0) +
+	     (opts.add_path ? 1 : 0) +
+	     (opts.remove_path ? 1 : 0)) > 1)
+		die("git checkout: --path, --full, --add-path and --remove-path are incompatible");
+
+	if (opts.new_branch && (opts.add_path || opts.remove_path))
+		die("git checkout: --add-path and --remove-path should only be used on current branch");
+
+	if (opts.new_branch && opts.no_narrow_checkout)
+		die("git checkout: switching branch with --full does not make sense");
+
 	if (opts.force && opts.merge)
 		die("git checkout: -f and -m are incompatible");
 
@@ -732,6 +773,9 @@ no_reference:
 		if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge)
 			die("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index.");
 
+		if (opts.no_narrow_checkout || opts.new_path || opts.add_path || opts.remove_path)
+			die("git checkout: updating paths is incompatible with setting sparse checkout");
+
 		return checkout_paths(source_tree, pathspec, &opts);
 	}
 
diff --git a/t/t2011-checkout-narrow.sh b/t/t2011-checkout-narrow.sh
new file mode 100755
index 0000000..77b99e1
--- /dev/null
+++ b/t/t2011-checkout-narrow.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+test_description='narrow checkout'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	mkdir work1 work2 work3
+	touch one two three
+	touch work1/one work2/two work3/three
+	git add one work1/one
+	git commit -m work1
+	git add two work2/two
+	git commit -m work2
+	git add three work3/three
+	git commit -m work3
+'
+
+test_expect_success '--full on no-narrow checkout' '
+	git checkout --full
+'
+
+test_expect_success '--full and --path incompatible' '
+	test_must_fail git checkout --full --path=work1
+'
+
+test_expect_success 'limit worktree to work1 and work2' '
+	git checkout --path="work1/*:work2/*" &&
+	test -f work1/one &&
+	test -f work2/two &&
+	! test -f work3/three
+'
+
+test_expect_success 'update worktree to work2 and work3' '
+	git checkout --path="work2/*:work3/*" &&
+	! test -f work1/one &&
+	test -f work2/two &&
+	test -f work3/three
+'
+
+test_expect_success 'update narrow prefix with modification' '
+	echo modified >> work2/two &&
+	git checkout --path="work1/*:work2/*" &&
+	test -f work1/one &&
+	test -f work2/two &&
+	! test -f work3/three &&
+	grep -q modified work2/two
+'
+
+test_expect_success 'update narrow should not lose modification' '
+	! git checkout --path="work1/*:work3/*" &&
+	test -f work1/one &&
+	test -f work2/two &&
+	! test -f work3/three &&
+	grep -q modified work2/two
+'
+
+test_expect_success 'widen checkout area' '
+	git checkout --add-path="work3/*" &&
+	test -f work1/one &&
+	test -f work2/two &&
+	test -f work3/three
+'
+
+test_expect_success 'narrow checkout area' '
+	git checkout --remove-path="work3/*" &&
+	test -f work1/one &&
+	test -f work2/two &&
+	! test -f work3/three
+'
+
+test_expect_success 'exit narrow checkout' '
+	git checkout --full &&
+	test -f work1/one &&
+	test -f work2/two &&
+	test -f work3/three &&
+	test one
+'
+
+test_done
-- 
1.6.0.96.g2fad1.dirty

  reply	other threads:[~2008-09-14 13:11 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-14 13:07 [PATCH 00/16] Narrow/Partial/Sparse checkout Nguyễn Thái Ngọc Duy
2008-09-14 13:07 ` [PATCH 01/16] Extend index to save more flags Nguyễn Thái Ngọc Duy
2008-09-14 13:07   ` [PATCH 02/16] Introduce CE_NO_CHECKOUT bit Nguyễn Thái Ngọc Duy
2008-09-14 13:07     ` [PATCH 03/16] update-index: refactor mark_valid() in preparation for new options Nguyễn Thái Ngọc Duy
2008-09-14 13:07       ` [PATCH 04/16] update-index: add --checkout/--no-checkout to update CE_NO_CHECKOUT bit Nguyễn Thái Ngọc Duy
2008-09-14 13:07         ` [PATCH 05/16] ls-files: add --narrow-checkout option to "will checkout" entries Nguyễn Thái Ngọc Duy
2008-09-14 13:07           ` [PATCH 06/16] Add tests for updating no-checkout entries in index Nguyễn Thái Ngọc Duy
2008-09-14 13:07             ` [PATCH 07/16] Prevent diff machinery from examining worktree outside narrow checkout Nguyễn Thái Ngọc Duy
2008-09-14 13:07               ` [PATCH 08/16] checkout_entry(): CE_NO_CHECKOUT on checked out entries Nguyễn Thái Ngọc Duy
2008-09-14 13:07                 ` [PATCH 09/16] ls-files: apply --deleted on narrow area only Nguyễn Thái Ngọc Duy
2008-09-14 13:07                   ` [PATCH 10/16] grep: skip files that have not been checked out Nguyễn Thái Ngọc Duy
2008-09-14 13:08                     ` [PATCH 11/16] unpack_trees(): add support for narrow checkout Nguyễn Thái Ngọc Duy
2008-09-14 13:08                       ` [PATCH 12/16] narrow spec: put '+' before a spec will change semantic of '*' Nguyễn Thái Ngọc Duy
2008-09-14 13:08                         ` [PATCH 13/16] ls-files: add --narrow-match=spec option for testing narrow matching Nguyễn Thái Ngọc Duy
2008-09-14 13:08                           ` [PATCH 14/16] clone: support narrow checkout with --path option Nguyễn Thái Ngọc Duy
2008-09-14 13:08                             ` Nguyễn Thái Ngọc Duy [this message]
2008-09-14 13:08                               ` [PATCH 16/16] ls-files: add --overlay option Nguyễn Thái Ngọc Duy
2008-09-14 21:10                                 ` Jakub Narebski
2008-09-15 19:35                                 ` Junio C Hamano
2008-09-16 12:00                                   ` Nguyen Thai Ngoc Duy
2008-09-16 17:00                                     ` Junio C Hamano
2008-09-14 21:12                               ` [PATCH 15/16] checkout: add new options to support narrow checkout Jakub Narebski
2008-09-16  9:53                               ` Baz
2008-09-16 10:17                               ` Johannes Sixt
2008-09-16 13:13                                 ` Nguyen Thai Ngoc Duy
2008-09-14 19:01                             ` [PATCH 14/16] clone: support narrow checkout with --path option Jakub Narebski
2008-09-15 20:27                               ` Junio C Hamano
2008-09-14 18:58                           ` [PATCH 13/16] ls-files: add --narrow-match=spec option for testing narrow matching Jakub Narebski
2008-09-15 19:34                       ` [PATCH 11/16] unpack_trees(): add support for narrow checkout Junio C Hamano
2008-09-16 11:45                         ` Nguyen Thai Ngoc Duy
2008-09-14 18:56                     ` [PATCH 10/16] grep: skip files that have not been checked out Jakub Narebski
2008-09-15 19:35                   ` [PATCH 09/16] ls-files: apply --deleted on narrow area only Junio C Hamano
2008-09-14 18:55           ` [PATCH 05/16] ls-files: add --narrow-checkout option to "will checkout" entries Jakub Narebski
2008-09-15 20:20             ` Junio C Hamano
2008-09-14 18:50         ` [PATCH 04/16] update-index: add --checkout/--no-checkout to update CE_NO_CHECKOUT bit Jakub Narebski
     [not found] <48cdde2837b2d_12d73fc6eb2c355c27876@app02.zenbe.com.tmail>
2008-09-15 10:40 ` [PATCH 15/16] checkout: add new options to support narrow checkout Jakub Narebski
2008-09-15 14:01   ` Nguyen Thai Ngoc Duy
2008-09-15 20:05     ` Jakub Narebski
2008-09-16 12:21       ` Nguyen Thai Ngoc Duy
2008-09-17  9:07         ` Jakub Narebski
2008-09-17 13:49           ` Nguyen Thai Ngoc Duy
2008-09-17 16:32             ` Johannes Sixt
2008-09-17 16:43               ` Nguyen Thai Ngoc Duy
2008-09-17 21:31             ` Jakub Narebski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1221397685-27715-16-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.