Merge branch 'ra/rev-parse-exclude-glob'
authorJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2018 09:23:56 +0000 (18:23 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2018 09:23:56 +0000 (18:23 +0900)
"rev-parse --exclude=<pattern> --branches=<pattern>" etc. did not
quite work, which has been corrected.

* ra/rev-parse-exclude-glob:
refs: fix some exclude patterns being ignored
refs: show --exclude failure with --branches/tags/remotes=glob

1  2 
refs.c
t/t6018-rev-list-glob.sh
diff --combined refs.c
index 17e4307f3171697ddd8c1e49710c16218e6774a8,539f385f61c94f4d5434ac6c2b5dbe1fb5ebcc73..f9936355cda6a1515f3192151f7fc14d0c2d7522
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -217,6 -217,7 +217,7 @@@ char *resolve_refdup(const char *refnam
  /* The argument to filter_refs */
  struct ref_filter {
        const char *pattern;
+       const char *prefix;
        each_ref_fn *fn;
        void *cb_data;
  };
@@@ -296,6 -297,8 +297,8 @@@ static int filter_refs(const char *refn
  
        if (wildmatch(filter->pattern, refname, 0))
                return 0;
+       if (filter->prefix)
+               skip_prefix(refname, filter->prefix, &refname);
        return filter->fn(refname, oid, flags, filter->cb_data);
  }
  
@@@ -458,6 -461,7 +461,7 @@@ int for_each_glob_ref_in(each_ref_fn fn
        }
  
        filter.pattern = real_pattern.buf;
+       filter.prefix = prefix;
        filter.fn = fn;
        filter.cb_data = cb_data;
        ret = for_each_ref(filter_refs, &filter);
@@@ -624,7 -628,6 +628,7 @@@ int dwim_log(const char *str, int len, 
  static int is_per_worktree_ref(const char *refname)
  {
        return !strcmp(refname, "HEAD") ||
 +              starts_with(refname, "refs/worktree/") ||
                starts_with(refname, "refs/bisect/") ||
                starts_with(refname, "refs/rewritten/");
  }
@@@ -641,34 -644,13 +645,34 @@@ static int is_pseudoref_syntax(const ch
        return 1;
  }
  
 +static int is_main_pseudoref_syntax(const char *refname)
 +{
 +      return skip_prefix(refname, "main-worktree/", &refname) &&
 +              *refname &&
 +              is_pseudoref_syntax(refname);
 +}
 +
 +static int is_other_pseudoref_syntax(const char *refname)
 +{
 +      if (!skip_prefix(refname, "worktrees/", &refname))
 +              return 0;
 +      refname = strchr(refname, '/');
 +      if (!refname || !refname[1])
 +              return 0;
 +      return is_pseudoref_syntax(refname + 1);
 +}
 +
  enum ref_type ref_type(const char *refname)
  {
        if (is_per_worktree_ref(refname))
                return REF_TYPE_PER_WORKTREE;
        if (is_pseudoref_syntax(refname))
                return REF_TYPE_PSEUDOREF;
 -       return REF_TYPE_NORMAL;
 +      if (is_main_pseudoref_syntax(refname))
 +              return REF_TYPE_MAIN_PSEUDOREF;
 +      if (is_other_pseudoref_syntax(refname))
 +              return REF_TYPE_OTHER_PSEUDOREF;
 +      return REF_TYPE_NORMAL;
  }
  
  long get_files_ref_lock_timeout_ms(void)
@@@ -724,7 -706,7 +728,7 @@@ static int write_pseudoref(const char *
                                    pseudoref);
                        rollback_lock_file(&lock);
                        goto done;
 -              } else if (oidcmp(&actual_old_oid, old_oid)) {
 +              } else if (!oideq(&actual_old_oid, old_oid)) {
                        strbuf_addf(err, _("unexpected object ID when writing '%s'"),
                                    pseudoref);
                        rollback_lock_file(&lock);
@@@ -766,7 -748,7 +770,7 @@@ static int delete_pseudoref(const char 
                }
                if (read_ref(pseudoref, &actual_old_oid))
                        die(_("could not read ref '%s'"), pseudoref);
 -              if (oidcmp(&actual_old_oid, old_oid)) {
 +              if (!oideq(&actual_old_oid, old_oid)) {
                        error(_("unexpected object ID when deleting '%s'"),
                              pseudoref);
                        rollback_lock_file(&lock);
@@@ -897,13 -879,13 +901,13 @@@ static int read_ref_at_ent(struct objec
                 */
                if (!is_null_oid(&cb->ooid)) {
                        oidcpy(cb->oid, noid);
 -                      if (oidcmp(&cb->ooid, noid))
 +                      if (!oideq(&cb->ooid, noid))
                                warning(_("log for ref %s has gap after %s"),
                                        cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
                }
                else if (cb->date == cb->at_time)
                        oidcpy(cb->oid, noid);
 -              else if (oidcmp(noid, cb->oid))
 +              else if (!oideq(noid, cb->oid))
                        warning(_("log for ref %s unexpectedly ended on %s"),
                                cb->refname, show_date(cb->date, cb->tz,
                                                       DATE_MODE(RFC2822)));
@@@ -1416,50 -1398,17 +1420,50 @@@ struct ref_iterator *refs_ref_iterator_
   * non-zero value, stop the iteration and return that value;
   * otherwise, return 0.
   */
 +static int do_for_each_repo_ref(struct repository *r, const char *prefix,
 +                              each_repo_ref_fn fn, int trim, int flags,
 +                              void *cb_data)
 +{
 +      struct ref_iterator *iter;
 +      struct ref_store *refs = get_main_ref_store(r);
 +
 +      if (!refs)
 +              return 0;
 +
 +      iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
 +
 +      return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
 +}
 +
 +struct do_for_each_ref_help {
 +      each_ref_fn *fn;
 +      void *cb_data;
 +};
 +
 +static int do_for_each_ref_helper(struct repository *r,
 +                                const char *refname,
 +                                const struct object_id *oid,
 +                                int flags,
 +                                void *cb_data)
 +{
 +      struct do_for_each_ref_help *hp = cb_data;
 +
 +      return hp->fn(refname, oid, flags, hp->cb_data);
 +}
 +
  static int do_for_each_ref(struct ref_store *refs, const char *prefix,
                           each_ref_fn fn, int trim, int flags, void *cb_data)
  {
        struct ref_iterator *iter;
 +      struct do_for_each_ref_help hp = { fn, cb_data };
  
        if (!refs)
                return 0;
  
        iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
  
 -      return do_for_each_ref_iterator(iter, fn, cb_data);
 +      return do_for_each_repo_ref_iterator(the_repository, iter,
 +                                      do_for_each_ref_helper, &hp);
  }
  
  int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
@@@ -1504,11 -1453,12 +1508,11 @@@ int refs_for_each_fullref_in(struct ref
        return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
  }
  
 -int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data)
 +int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
  {
 -      return do_for_each_ref(get_main_ref_store(r),
 -                             git_replace_ref_base, fn,
 -                             strlen(git_replace_ref_base),
 -                             DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 +      return do_for_each_repo_ref(r, git_replace_ref_base, fn,
 +                                  strlen(git_replace_ref_base),
 +                                  DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
  }
  
  int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@@ -2087,12 -2037,10 +2091,12 @@@ cleanup
  int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
  {
        struct ref_iterator *iter;
 +      struct do_for_each_ref_help hp = { fn, cb_data };
  
        iter = refs->be->reflog_iterator_begin(refs);
  
 -      return do_for_each_ref_iterator(iter, fn, cb_data);
 +      return do_for_each_repo_ref_iterator(the_repository, iter,
 +                                           do_for_each_ref_helper, &hp);
  }
  
  int for_each_reflog(each_ref_fn fn, void *cb_data)
diff --combined t/t6018-rev-list-glob.sh
index 270e579c2d3a30b2a08517bc63fe6edf5221af59,7dc6cbdc421d83e6cd83823ef0c8b199fee6d19c..bb5aeac07f8341ed44bfe25aba6238a92e1fc9e7
@@@ -36,7 -36,13 +36,13 @@@ test_expect_success 'setup' 
        git tag foo/bar master &&
        commit master3 &&
        git update-ref refs/remotes/foo/baz master &&
-       commit master4
+       commit master4 &&
+       git update-ref refs/remotes/upstream/one subspace/one &&
+       git update-ref refs/remotes/upstream/two subspace/two &&
+       git update-ref refs/remotes/upstream/x subspace-x &&
+       git tag qux/one subspace/one &&
+       git tag qux/two subspace/two &&
+       git tag qux/x subspace-x
  '
  
  test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
@@@ -141,18 -147,54 +147,66 @@@ test_expect_success 'rev-parse accumula
        compare rev-parse "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches
  '
  
 +test_expect_success 'rev-parse --branches clears --exclude' '
 +      compare rev-parse "--exclude=* --branches --branches" "--branches"
 +'
 +
 +test_expect_success 'rev-parse --tags clears --exclude' '
 +      compare rev-parse "--exclude=* --tags --tags" "--tags"
 +'
 +
 +test_expect_success 'rev-parse --all clears --exclude' '
 +      compare rev-parse "--exclude=* --all --all" "--all"
 +'
 +
+ test_expect_success 'rev-parse --exclude=glob with --branches=glob' '
+       compare rev-parse "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
+ '
+ test_expect_success 'rev-parse --exclude=glob with --tags=glob' '
+       compare rev-parse "--exclude=qux/? --tags=qux/*" "qux/one qux/two"
+ '
+ test_expect_success 'rev-parse --exclude=glob with --remotes=glob' '
+       compare rev-parse "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two"
+ '
+ test_expect_success 'rev-parse --exclude=ref with --branches=glob' '
+       compare rev-parse "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two"
+ '
+ test_expect_success 'rev-parse --exclude=ref with --tags=glob' '
+       compare rev-parse "--exclude=qux/x --tags=qux/*" "qux/one qux/two"
+ '
+ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '
+       compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
+ '
+ test_expect_success 'rev-list --exclude=glob with --branches=glob' '
+       compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
+ '
+ test_expect_success 'rev-list --exclude=glob with --tags=glob' '
+       compare rev-list "--exclude=qux/? --tags=qux/*" "qux/one qux/two"
+ '
+ test_expect_success 'rev-list --exclude=glob with --remotes=glob' '
+       compare rev-list "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two"
+ '
+ test_expect_success 'rev-list --exclude=ref with --branches=glob' '
+       compare rev-list "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two"
+ '
+ test_expect_success 'rev-list --exclude=ref with --tags=glob' '
+       compare rev-list "--exclude=qux/x --tags=qux/*" "qux/one qux/two"
+ '
+ test_expect_success 'rev-list --exclude=ref with --remotes=glob' '
+       compare rev-list "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
+ '
  test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
  
        compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
@@@ -245,7 -287,7 +299,7 @@@ test_expect_success 'rev-list --tags=fo
  
  test_expect_success 'rev-list --tags' '
  
-       compare rev-list "foo/bar" "--tags"
+       compare rev-list "foo/bar qux/x qux/two qux/one" "--tags"
  
  '
  
@@@ -267,7 -309,7 +321,7 @@@ test_expect_success 'rev-list accumulat
        compare rev-list "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches
  '
  
 -test_expect_failure 'rev-list should succeed with empty output on empty stdin' '
 +test_expect_success 'rev-list should succeed with empty output on empty stdin' '
        git rev-list --stdin </dev/null >actual &&
        test_must_be_empty actual
  '
@@@ -304,7 -346,7 +358,7 @@@ test_expect_success 'shortlog accepts -
          "master other/three someref subspace-x subspace/one subspace/two" \
          "--glob=heads/*" &&
        compare shortlog foo/bar --tags=foo &&
-       compare shortlog foo/bar --tags &&
+       compare shortlog "foo/bar qux/one qux/two qux/x" --tags &&
        compare shortlog foo/baz --remotes=foo
  
  '