From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH 6/9] Add support for narrow checkout in unpack_trees()
Date: Fri, 15 Aug 2008 21:26:38 +0700 [thread overview]
Message-ID: <20080815142638.GA10736@laptop> (raw)
In-Reply-To: <cover.1218807249.git.pclouds@gmail.com>
This patch teaches unpack_trees() to checkout/remove entries
on working directories appropriately when narrow area is
changed. There are three kind of changes:
- new_narrow_path: reset workdir to a new narrow checkout
- add_narrow_path: keep current narrow areas and add more entries
- remove_narrow_path: remove some entries from current narrow areas
CE_WD_REMOVE is introduced to remove entries from working directories,
but still keep them in index
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
cache.h | 3 ++
unpack-trees.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
unpack-trees.h | 4 ++
3 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/cache.h b/cache.h
index 86288b6..f502b28 100644
--- a/cache.h
+++ b/cache.h
@@ -139,6 +139,9 @@ struct cache_entry {
#define CE_HASHED (0x100000)
#define CE_UNHASHED (0x200000)
+/* Only remove in work directory, not index */
+#define CE_WD_REMOVE (0x400000)
+
/* "Assume unchanged" mask */
#define CE_VALID_MASK (CE_VALID | CE_NO_CHECKOUT)
diff --git a/unpack-trees.c b/unpack-trees.c
index cba0aca..022c643 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -96,6 +96,21 @@ static int check_updates(struct unpack_trees_options *o)
if (o->update && o->verbose_update) {
for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
struct cache_entry *ce = index->cache[cnt];
+
+ /*
+ * Special case: CE_WD_REMOVE may be set along with CE_NO_CHECKOUT
+ * when some files are going to leave narrow checkout, so it must
+ * go before ce_no_checkout() check
+ */
+ if (ce->ce_flags & CE_WD_REMOVE) {
+ total++;
+ continue;
+ }
+
+ /* Now if there is any update outside narrow, ignore it */
+ if (ce_no_checkout(ce))
+ continue;
+
if (ce->ce_flags & (CE_UPDATE | CE_REMOVE))
total++;
}
@@ -108,6 +123,18 @@ static int check_updates(struct unpack_trees_options *o)
for (i = 0; i < index->cache_nr; i++) {
struct cache_entry *ce = index->cache[i];
+ /* As stated earlier, CE_WD_REMOVE must bypass ce_no_checkout() check */
+ if (ce->ce_flags & CE_WD_REMOVE) {
+ display_progress(progress, ++cnt);
+ if (o->update)
+ unlink_entry(ce);
+ continue;
+ }
+
+ /* Now if there is any update outside narrow, ignore it */
+ if (ce_no_checkout(ce))
+ continue;
+
if (ce->ce_flags & CE_REMOVE) {
display_progress(progress, ++cnt);
if (o->update)
@@ -121,6 +148,9 @@ static int check_updates(struct unpack_trees_options *o)
for (i = 0; i < index->cache_nr; i++) {
struct cache_entry *ce = index->cache[i];
+ if (ce_no_checkout(ce))
+ continue;
+
if (ce->ce_flags & CE_UPDATE) {
display_progress(progress, ++cnt);
ce->ce_flags &= ~CE_UPDATE;
@@ -725,6 +755,58 @@ static void show_stage_entry(FILE *o,
}
#endif
+int match_narrow_spec(const char *spec_, const char *path)
+{
+ int match = 0;
+ char *spec, *cur_spec;
+
+ if (!spec_)
+ return 1; /* always match if spec_ is NULL */
+ spec = cur_spec = xstrdup(spec_);
+
+ while (!match) {
+ char *next_spec = strchr(cur_spec, ':');
+ if (!next_spec) {
+ if (!fnmatch(cur_spec, path, 0))
+ match = 1;
+ break;
+ }
+ *next_spec = '\0';
+ if (!fnmatch(cur_spec, path, 0))
+ match = 1;
+ cur_spec = next_spec+1;
+ }
+ free(spec);
+ return match;
+}
+
+static int apply_narrow_checkout(struct cache_entry *ce, struct cache_entry *old_ce, struct unpack_trees_options *o)
+{
+ int checkout;
+ int was_no_checkout = old_ce && ce_no_checkout(old_ce);
+
+ if (!(o->new_narrow_path | o->add_narrow_path | o->remove_narrow_path))
+ return 0;
+
+ checkout = match_narrow_spec(o->narrow_spec, ce->name);
+
+ /*
+ * The logic is a bit twisted here, when we expand checkout (add_narrow_path)
+ * we narrow no_checkout area. Similarly when we narrow checkout
+ * (remove_narrow_path), we expand no_checkout area. So there are three cases:
+ *
+ * [1] New narrow spec: do not care about old_ce
+ * [2] Expand spec: mark no_checkout if no_checkout previously _and_ now too
+ * [3] Narrow spec: mark no_checkout if previously no_checkout _or_ now checkout
+ */
+ if ((o->new_narrow_path && !checkout) /* [1] */
+ || (o->add_narrow_path && !checkout && was_no_checkout) /* [2] */
+ || (o->remove_narrow_path && (checkout || was_no_checkout))) /* [3] */
+ ce_mark_no_checkout(ce);
+
+ return 1;
+}
+
int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o)
{
struct cache_entry *index;
@@ -899,6 +981,7 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
struct cache_entry *current = src[0];
struct cache_entry *oldtree = src[1];
struct cache_entry *newtree = src[2];
+ int has_narrow_checkout = 0;
if (o->merge_size != 2)
return error("Cannot do a twoway merge of %d trees",
@@ -909,6 +992,9 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
if (newtree == o->df_conflict_entry)
newtree = NULL;
+ if (newtree)
+ has_narrow_checkout = apply_narrow_checkout(newtree, current, o);
+
if (current) {
if ((!oldtree && !newtree) || /* 4 and 5 */
(!oldtree && newtree &&
@@ -918,6 +1004,21 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
(oldtree && newtree &&
!same(oldtree, newtree) && /* 18 and 19 */
same(current, newtree))) {
+ if (has_narrow_checkout) {
+ /* enter narrow checkout, keep entry and add to workdir */
+ if (ce_no_checkout(current) && ce_checkout(newtree)) {
+ add_entry(o, current, CE_UPDATE, CE_NO_CHECKOUT);
+ return 1;
+ }
+
+ /* leave narrow checkout, keep entry and remove from workdir */
+ if (ce_checkout(current) && ce_no_checkout(newtree)) {
+ if (verify_uptodate(current, o))
+ return -1;
+ add_entry(o, current, CE_WD_REMOVE | CE_NO_CHECKOUT, 0);
+ return 1;
+ }
+ }
return keep_entry(current, o);
}
else if (oldtree && !newtree && same(current, oldtree)) {
@@ -927,6 +1028,9 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
else if (oldtree && newtree &&
same(current, oldtree) && !same(current, newtree)) {
/* 20 or 21 */
+ /* enter narrow checkout, make sure always add */
+ if (has_narrow_checkout && ce_no_checkout(current) && ce_checkout(newtree))
+ newtree->ce_flags |= CE_UPDATE;
return merged_entry(newtree, current, o);
}
else {
@@ -987,6 +1091,8 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
if (!a)
return deleted_entry(old, old, o);
+ apply_narrow_checkout(a, NULL, o);
+
if (old && same(old, a)) {
int update = 0;
if (o->reset) {
diff --git a/unpack-trees.h b/unpack-trees.h
index 94e5672..880cef8 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -26,6 +26,9 @@ struct unpack_trees_options {
verbose_update:1,
aggressive:1,
skip_unmerged:1,
+ new_narrow_path:1,
+ add_narrow_path:2,
+ remove_narrow_path:2,
gently:1;
const char *prefix;
int pos;
@@ -37,6 +40,7 @@ struct unpack_trees_options {
int merge_size;
struct cache_entry *df_conflict_entry;
+ const char *narrow_spec;
void *unpack_data;
struct index_state *dst_index;
--
1.6.0.rc3.250.g8dd0
next prev parent reply other threads:[~2008-08-15 14:28 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1218807249.git.pclouds@gmail.com>
2008-08-15 14:24 ` [PATCH 1/9] Introduce CE_NO_CHECKOUT bit Nguyễn Thái Ngọc Duy
2008-08-15 14:25 ` [PATCH 2/9] update-index: add --checkout/--no-checkout options to update " Nguyễn Thái Ngọc Duy
2008-08-15 14:25 ` [PATCH 3/9] ls-files: add --checkout option to show checked out files Nguyễn Thái Ngọc Duy
2008-08-15 14:26 ` [PATCH 4/9] Prevent diff machinery from examining worktree outside narrow checkout Nguyễn Thái Ngọc Duy
2008-08-15 14:26 ` [PATCH 5/9] Clear CE_NO_CHECKOUT on checked out entries Nguyễn Thái Ngọc Duy
2008-08-15 14:26 ` Nguyễn Thái Ngọc Duy [this message]
2008-08-15 14:26 ` [PATCH 7/9] ls-files: add --narrow-match=spec option to test narrow matching Nguyễn Thái Ngọc Duy
2008-08-15 14:27 ` [PATCH 8/9] clone: support narrow checkout with --path option Nguyễn Thái Ngọc Duy
2008-08-15 14:27 ` [PATCH 9/9] checkout: add new options to support narrow checkout Nguyễn Thái Ngọc Duy
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=20080815142638.GA10736@laptop \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).