From: Thiago Farina <tfransosi@gmail.com>
To: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>,
skillzero@gmail.com
Subject: Re: [PATCH 3/3] sparse checkout: do not eagerly decide the fate for whole directory
Date: Mon, 2 May 2011 23:14:21 -0300 [thread overview]
Message-ID: <BANLkTikgNR1G5_TO3rmMZy3fN2PNF2Pqjg@mail.gmail.com> (raw)
In-Reply-To: <1304340464-14829-3-git-send-email-pclouds@gmail.com>
2011/5/2 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
> Sparse-setting code follows closely how files are excluded in
> read_directory(), every entry (including directories) are fed to
> excluded_from_list() to decide if the entry is suitable. Directories
> are treated no different than files. If a directory is matched (or
> not), the whole directory is considered matched (or not) and the
> process moves on.
>
> This generally works as long as there are no patterns to exclude parts
> of the directory. In case of sparse checkout code, the following patterns
>
> t
> !t/t0000-basic.sh
>
> will produce a worktree with full directory "t" even if t0000-basic.sh
> is requested to stay out.
>
> By the same reasoning, if a directory is to be excluded, any rules to
> re-include certain files within that directory will be ignored.
>
> Fix it by always checking files against patterns. If no pattern can
> decide (ie. excluded_from_list() returns -1), those files will be
Maybe: can be decided?
> included/excluded as same as their parent directory.
>
> Noticed-by: <skillzero@gmail.com>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> The TODO better be solved once read_directory() fixes the same fault.
> I have a feeling that some code can be shared..
>
> t/t1011-read-tree-sparse-checkout.sh | 41 ++++++++++++++++++++++
> unpack-trees.c | 63 ++++++++++++++++++---------------
> 2 files changed, 75 insertions(+), 29 deletions(-)
>
> diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
> index 3f9d66f..20a50eb 100755
> --- a/t/t1011-read-tree-sparse-checkout.sh
> +++ b/t/t1011-read-tree-sparse-checkout.sh
> @@ -106,6 +106,47 @@ test_expect_success 'match directories without trailing slash' '
> test -f sub/added
> '
>
> +test_expect_success 'match directories with negated patterns' '
> + cat >expected.swt-negation <<\EOF &&
> +S init.t
> +S sub/added
> +H sub/addedtoo
> +S subsub/added
> +EOF
> +
> + cat >.git/info/sparse-checkout <<\EOF &&
> +sub
> +!sub/added
> +EOF
> + git read-tree -m -u HEAD &&
> + git ls-files -t >result &&
> + test_cmp expected.swt-negation result &&
> + test ! -f init.t &&
> + test ! -f sub/added &&
> + test -f sub/addedtoo
> +'
> +
> +test_expect_success 'match directories with negated patterns (2)' '
> + cat >expected.swt-negation2 <<\EOF &&
> +H init.t
> +H sub/added
> +S sub/addedtoo
> +H subsub/added
> +EOF
> +
> + cat >.git/info/sparse-checkout <<\EOF &&
> +/*
> +!sub
> +sub/added
> +EOF
> + git read-tree -m -u HEAD &&
> + git ls-files -t >result &&
> + test_cmp expected.swt-negation2 result &&
> + test -f init.t &&
> + test -f sub/added &&
> + test ! -f sub/addedtoo
> +'
> +
> test_expect_success 'match directory pattern' '
> echo "s?b" >.git/info/sparse-checkout &&
> git read-tree -m -u HEAD &&
> diff --git a/unpack-trees.c b/unpack-trees.c
> index 500ebcf..5b8419c 100644
> --- a/unpack-trees.c
> +++ b/unpack-trees.c
> @@ -814,43 +814,45 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
> return mask;
> }
>
> +static int clear_ce_flags_1(struct cache_entry **cache, int nr,
> + char *prefix, int prefix_len,
> + int select_mask, int clear_mask,
> + struct exclude_list *el, int defval);
> +
> /* Whole directory matching */
> static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
> char *prefix, int prefix_len,
> char *basename,
> int select_mask, int clear_mask,
> - struct exclude_list *el)
> + struct exclude_list *el, int defval)
> {
> - struct cache_entry **cache_end = cache + nr;
> + struct cache_entry **cache_end;
> int dtype = DT_DIR;
> int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el);
>
> prefix[prefix_len++] = '/';
>
> - /* included, no clearing for any entries under this directory */
> - if (!ret) {
> - for (; cache != cache_end; cache++) {
> - struct cache_entry *ce = *cache;
> - if (strncmp(ce->name, prefix, prefix_len))
> - break;
> - }
> - return nr - (cache_end - cache);
> - }
> + /* If undecided, use parent directory's decision in defval */
What means "use parent directory's decision"? Could you make this
comment more clearer?
> + if (ret < 0)
> + ret = defval;
>
> - /* excluded, clear all selected entries under this directory. */
Start with capital letter?
> - if (ret == 1) {
> - for (; cache != cache_end; cache++) {
> - struct cache_entry *ce = *cache;
> - if (select_mask && !(ce->ce_flags & select_mask))
> - continue;
> - if (strncmp(ce->name, prefix, prefix_len))
> - break;
> - ce->ce_flags &= ~clear_mask;
> - }
> - return nr - (cache_end - cache);
> + for (cache_end = cache; cache_end != cache + nr; cache_end++) {
> + struct cache_entry *ce = *cache_end;
> + if (strncmp(ce->name, prefix, prefix_len))
> + break;
> }
>
> - return 0;
> + /*
> + * TODO: check el, if there are no patterns that may conflict
> + * with ret (iow, we know in advance the the incl/excl
the the ?
> + * decision for the entire directory), clear flag here without
> + * calling clear_ce_flags_1(). That function will call
> + * the expensive excluded_from_list() on every entry.
> + */
> + return clear_ce_flags_1(cache, cache_end - cache,
> + prefix, prefix_len,
> + select_mask, clear_mask,
> + el, ret);
> }
>
> /*
> @@ -871,7 +873,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
> static int clear_ce_flags_1(struct cache_entry **cache, int nr,
> char *prefix, int prefix_len,
> int select_mask, int clear_mask,
> - struct exclude_list *el)
> + struct exclude_list *el, int defval)
> {
> struct cache_entry **cache_end = cache + nr;
>
> @@ -882,7 +884,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
> while(cache != cache_end) {
> struct cache_entry *ce = *cache;
> const char *name, *slash;
> - int len, dtype;
> + int len, dtype, ret;
>
> if (select_mask && !(ce->ce_flags & select_mask)) {
> cache++;
> @@ -911,7 +913,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
> prefix, prefix_len + len,
> prefix + prefix_len,
> select_mask, clear_mask,
> - el);
> + el, defval);
>
> /* clear_c_f_dir eats a whole dir already? */
> if (processed) {
> @@ -922,13 +924,16 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
> prefix[prefix_len + len++] = '/';
> cache += clear_ce_flags_1(cache, cache_end - cache,
> prefix, prefix_len + len,
> - select_mask, clear_mask, el);
> + select_mask, clear_mask, el, defval);
> continue;
> }
>
> /* Non-directory */
> dtype = ce_to_dtype(ce);
> - if (excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el) > 0)
> + ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el);
> + if (ret < 0)
> + ret = defval;
> + if (ret > 0)
> ce->ce_flags &= ~clear_mask;
> cache++;
> }
> @@ -943,7 +948,7 @@ static int clear_ce_flags(struct cache_entry **cache, int nr,
> return clear_ce_flags_1(cache, nr,
> prefix, 0,
> select_mask, clear_mask,
> - el);
> + el, 0);
> }
>
> /*
> --
> 1.7.4.74.g639db
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
next prev parent reply other threads:[~2011-05-03 2:14 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-02 12:47 [PATCH 1/3] t3700: note a .gitignore matching fault Nguyễn Thái Ngọc Duy
2011-05-02 12:47 ` [PATCH 2/3] t1011: fix sparse-checkout initialization and add new file Nguyễn Thái Ngọc Duy
2011-05-02 12:47 ` [PATCH 3/3] sparse checkout: do not eagerly decide the fate for whole directory Nguyễn Thái Ngọc Duy
2011-05-03 2:14 ` Thiago Farina [this message]
2011-05-03 4:43 ` Nguyen Thai Ngoc Duy
2011-05-10 23:37 ` Junio C Hamano
2011-05-11 12:03 ` Nguyen Thai Ngoc Duy
[not found] ` <1304955781-13566-1-git-send-email-pclouds@gmail.com>
2011-05-09 22:22 ` Junio C Hamano
2011-05-02 12:55 ` [PATCH 1/3] t3700: note a .gitignore matching fault Nguyễn Thái Ngọc Duy
2011-05-02 15:01 ` Johannes Sixt
2011-05-02 15:52 ` Nguyen Thai Ngoc Duy
2011-05-03 17:56 ` Junio C Hamano
2011-05-03 23:43 ` Nguyen Thai Ngoc Duy
2011-05-03 23:57 ` Junio C Hamano
2011-05-04 0:41 ` Nguyen Thai Ngoc Duy
2011-05-04 1:05 ` Nguyen Thai Ngoc Duy
2011-05-04 6:06 ` Johannes Sixt
2011-05-04 6:22 ` Nguyen Thai Ngoc 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=BANLkTikgNR1G5_TO3rmMZy3fN2PNF2Pqjg@mail.gmail.com \
--to=tfransosi@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pclouds@gmail.com \
--cc=skillzero@gmail.com \
/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).