git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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
>

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