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 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.