mirror of
https://github.com/git/git.git
synced 2024-11-23 18:05:29 +08:00
Merge branch 'ps/pseudo-ref-terminology'
Terminology to call various ref-like things are getting straightened out. * ps/pseudo-ref-terminology: refs: refuse to write pseudorefs ref-filter: properly distinuish pseudo and root refs refs: pseudorefs are no refs refs: classify HEAD as a root ref refs: do not check ref existence in `is_root_ref()` refs: rename `is_special_ref()` to `is_pseudo_ref()` refs: rename `is_pseudoref()` to `is_root_ref()` Documentation/glossary: define root refs as refs Documentation/glossary: clarify limitations of pseudorefs Documentation/glossary: redefine pseudorefs as special refs
This commit is contained in:
commit
16a592f132
@ -497,20 +497,18 @@ exclude;;
|
|||||||
unusual refs.
|
unusual refs.
|
||||||
|
|
||||||
[[def_pseudoref]]pseudoref::
|
[[def_pseudoref]]pseudoref::
|
||||||
Pseudorefs are a class of files under `$GIT_DIR` which behave
|
A ref that has different semantics than normal refs. These refs can be
|
||||||
like refs for the purposes of rev-parse, but which are treated
|
read via normal Git commands, but cannot be written to by commands like
|
||||||
specially by git. Pseudorefs both have names that are all-caps,
|
linkgit:git-update-ref[1].
|
||||||
and always start with a line consisting of a
|
+
|
||||||
<<def_SHA1,SHA-1>> followed by whitespace. So, HEAD is not a
|
The following pseudorefs are known to Git:
|
||||||
pseudoref, because it is sometimes a symbolic ref. They might
|
|
||||||
optionally contain some additional data. `MERGE_HEAD` and
|
- `FETCH_HEAD` is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
|
||||||
`CHERRY_PICK_HEAD` are examples. Unlike
|
may refer to multiple object IDs. Each object ID is annotated with metadata
|
||||||
<<def_per_worktree_ref,per-worktree refs>>, these files cannot
|
indicating where it was fetched from and its fetch status.
|
||||||
be symbolic refs, and never have reflogs. They also cannot be
|
|
||||||
updated through the normal ref update machinery. Instead,
|
- `MERGE_HEAD` is written by linkgit:git-merge[1] when resolving merge
|
||||||
they are updated by directly writing to the files. However,
|
conflicts. It contains all commit IDs which are being merged.
|
||||||
they can be read as if they were refs, so `git rev-parse
|
|
||||||
MERGE_HEAD` will work.
|
|
||||||
|
|
||||||
[[def_pull]]pull::
|
[[def_pull]]pull::
|
||||||
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
|
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
|
||||||
@ -552,20 +550,38 @@ exclude;;
|
|||||||
to the result.
|
to the result.
|
||||||
|
|
||||||
[[def_ref]]ref::
|
[[def_ref]]ref::
|
||||||
A name that begins with `refs/` (e.g. `refs/heads/master`)
|
A name that that points to an <<def_object_name,object name>> or
|
||||||
that points to an <<def_object_name,object name>> or another
|
another ref (the latter is called a <<def_symref,symbolic ref>>).
|
||||||
ref (the latter is called a <<def_symref,symbolic ref>>).
|
|
||||||
For convenience, a ref can sometimes be abbreviated when used
|
For convenience, a ref can sometimes be abbreviated when used
|
||||||
as an argument to a Git command; see linkgit:gitrevisions[7]
|
as an argument to a Git command; see linkgit:gitrevisions[7]
|
||||||
for details.
|
for details.
|
||||||
Refs are stored in the <<def_repository,repository>>.
|
Refs are stored in the <<def_repository,repository>>.
|
||||||
+
|
+
|
||||||
The ref namespace is hierarchical.
|
The ref namespace is hierarchical.
|
||||||
Different subhierarchies are used for different purposes (e.g. the
|
Ref names must either start with `refs/` or be located in the root of
|
||||||
`refs/heads/` hierarchy is used to represent local branches).
|
the hierarchy. For the latter, their name must follow these rules:
|
||||||
+
|
+
|
||||||
There are a few special-purpose refs that do not begin with `refs/`.
|
- The name consists of only upper-case characters or underscores.
|
||||||
The most notable example is `HEAD`.
|
|
||||||
|
- The name ends with "`_HEAD`" or is equal to "`HEAD`".
|
||||||
|
+
|
||||||
|
There are some irregular refs in the root of the hierarchy that do not
|
||||||
|
match these rules. The following list is exhaustive and shall not be
|
||||||
|
extended in the future:
|
||||||
|
+
|
||||||
|
- `AUTO_MERGE`
|
||||||
|
|
||||||
|
- `BISECT_EXPECTED_REV`
|
||||||
|
|
||||||
|
- `NOTES_MERGE_PARTIAL`
|
||||||
|
|
||||||
|
- `NOTES_MERGE_REF`
|
||||||
|
|
||||||
|
- `MERGE_AUTOSTASH`
|
||||||
|
+
|
||||||
|
Different subhierarchies are used for different purposes. For example,
|
||||||
|
the `refs/heads/` hierarchy is used to represent local branches whereas
|
||||||
|
the `refs/tags/` hierarchy is used to represent local tags..
|
||||||
|
|
||||||
[[def_reflog]]reflog::
|
[[def_reflog]]reflog::
|
||||||
A reflog shows the local "history" of a ref. In other words,
|
A reflog shows the local "history" of a ref. In other words,
|
||||||
@ -639,20 +655,6 @@ The most notable example is `HEAD`.
|
|||||||
An <<def_object,object>> used to temporarily store the contents of a
|
An <<def_object,object>> used to temporarily store the contents of a
|
||||||
<<def_dirty,dirty>> working directory and the index for future reuse.
|
<<def_dirty,dirty>> working directory and the index for future reuse.
|
||||||
|
|
||||||
[[def_special_ref]]special ref::
|
|
||||||
A ref that has different semantics than normal refs. These refs can be
|
|
||||||
accessed via normal Git commands but may not behave the same as a
|
|
||||||
normal ref in some cases.
|
|
||||||
+
|
|
||||||
The following special refs are known to Git:
|
|
||||||
|
|
||||||
- "`FETCH_HEAD`" is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
|
|
||||||
may refer to multiple object IDs. Each object ID is annotated with metadata
|
|
||||||
indicating where it was fetched from and its fetch status.
|
|
||||||
|
|
||||||
- "`MERGE_HEAD`" is written by linkgit:git-merge[1] when resolving merge
|
|
||||||
conflicts. It contains all commit IDs which are being merged.
|
|
||||||
|
|
||||||
[[def_submodule]]submodule::
|
[[def_submodule]]submodule::
|
||||||
A <<def_repository,repository>> that holds the history of a
|
A <<def_repository,repository>> that holds the history of a
|
||||||
separate project inside another repository (the latter of
|
separate project inside another repository (the latter of
|
||||||
|
@ -98,7 +98,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (include_root_refs)
|
if (include_root_refs)
|
||||||
flags |= FILTER_REFS_ROOT_REFS;
|
flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD;
|
||||||
|
|
||||||
filter.match_as_path = 1;
|
filter.match_as_path = 1;
|
||||||
filter_and_format_refs(&filter, flags, sorting, &format);
|
filter_and_format_refs(&filter, flags, sorting, &format);
|
||||||
|
16
ref-filter.c
16
ref-filter.c
@ -2634,7 +2634,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
|||||||
each_ref_fn cb,
|
each_ref_fn cb,
|
||||||
void *cb_data)
|
void *cb_data)
|
||||||
{
|
{
|
||||||
if (filter->kind == FILTER_REFS_KIND_MASK) {
|
if (filter->kind & FILTER_REFS_ROOT_REFS) {
|
||||||
/* In this case, we want to print all refs including root refs. */
|
/* In this case, we want to print all refs including root refs. */
|
||||||
return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
|
return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
|
||||||
cb, cb_data);
|
cb, cb_data);
|
||||||
@ -2764,8 +2764,10 @@ static int ref_kind_from_refname(const char *refname)
|
|||||||
return ref_kind[i].kind;
|
return ref_kind[i].kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_pseudoref(get_main_ref_store(the_repository), refname))
|
if (is_pseudo_ref(refname))
|
||||||
return FILTER_REFS_PSEUDOREFS;
|
return FILTER_REFS_PSEUDOREFS;
|
||||||
|
if (is_root_ref(refname))
|
||||||
|
return FILTER_REFS_ROOT_REFS;
|
||||||
|
|
||||||
return FILTER_REFS_OTHERS;
|
return FILTER_REFS_OTHERS;
|
||||||
}
|
}
|
||||||
@ -2802,11 +2804,11 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
|
|||||||
/*
|
/*
|
||||||
* Generally HEAD refs are printed with special description denoting a rebase,
|
* Generally HEAD refs are printed with special description denoting a rebase,
|
||||||
* detached state and so forth. This is useful when only printing the HEAD ref
|
* detached state and so forth. This is useful when only printing the HEAD ref
|
||||||
* But when it is being printed along with other pseudorefs, it makes sense to
|
* But when it is being printed along with other root refs, it makes sense to
|
||||||
* keep the formatting consistent. So we mask the type to act like a pseudoref.
|
* keep the formatting consistent. So we mask the type to act like a root ref.
|
||||||
*/
|
*/
|
||||||
if (filter->kind == FILTER_REFS_KIND_MASK && kind == FILTER_REFS_DETACHED_HEAD)
|
if (filter->kind & FILTER_REFS_ROOT_REFS && kind == FILTER_REFS_DETACHED_HEAD)
|
||||||
kind = FILTER_REFS_PSEUDOREFS;
|
kind = FILTER_REFS_ROOT_REFS;
|
||||||
else if (!(kind & filter->kind))
|
else if (!(kind & filter->kind))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -3086,7 +3088,7 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
|
|||||||
* When printing all ref types, HEAD is already included,
|
* When printing all ref types, HEAD is already included,
|
||||||
* so we don't want to print HEAD again.
|
* so we don't want to print HEAD again.
|
||||||
*/
|
*/
|
||||||
if (!ret && (filter->kind != FILTER_REFS_KIND_MASK) &&
|
if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) &&
|
||||||
(filter->kind & FILTER_REFS_DETACHED_HEAD))
|
(filter->kind & FILTER_REFS_DETACHED_HEAD))
|
||||||
refs_head_ref(get_main_ref_store(the_repository), fn,
|
refs_head_ref(get_main_ref_store(the_repository), fn,
|
||||||
cb_data);
|
cb_data);
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
FILTER_REFS_REMOTES | FILTER_REFS_OTHERS)
|
FILTER_REFS_REMOTES | FILTER_REFS_OTHERS)
|
||||||
#define FILTER_REFS_DETACHED_HEAD 0x0020
|
#define FILTER_REFS_DETACHED_HEAD 0x0020
|
||||||
#define FILTER_REFS_PSEUDOREFS 0x0040
|
#define FILTER_REFS_PSEUDOREFS 0x0040
|
||||||
#define FILTER_REFS_ROOT_REFS (FILTER_REFS_DETACHED_HEAD | FILTER_REFS_PSEUDOREFS)
|
#define FILTER_REFS_ROOT_REFS 0x0080
|
||||||
#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \
|
#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \
|
||||||
FILTER_REFS_PSEUDOREFS)
|
FILTER_REFS_PSEUDOREFS | FILTER_REFS_ROOT_REFS)
|
||||||
|
|
||||||
struct atom_value;
|
struct atom_value;
|
||||||
struct ref_sorting;
|
struct ref_sorting;
|
||||||
|
98
refs.c
98
refs.c
@ -819,7 +819,22 @@ int is_per_worktree_ref(const char *refname)
|
|||||||
starts_with(refname, "refs/rewritten/");
|
starts_with(refname, "refs/rewritten/");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_pseudoref_syntax(const char *refname)
|
int is_pseudo_ref(const char *refname)
|
||||||
|
{
|
||||||
|
static const char * const pseudo_refs[] = {
|
||||||
|
"FETCH_HEAD",
|
||||||
|
"MERGE_HEAD",
|
||||||
|
};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(pseudo_refs); i++)
|
||||||
|
if (!strcmp(refname, pseudo_refs[i]))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_root_ref_syntax(const char *refname)
|
||||||
{
|
{
|
||||||
const char *c;
|
const char *c;
|
||||||
|
|
||||||
@ -828,56 +843,37 @@ static int is_pseudoref_syntax(const char *refname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* HEAD is not a pseudoref, but it certainly uses the
|
|
||||||
* pseudoref syntax.
|
|
||||||
*/
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_pseudoref(struct ref_store *refs, const char *refname)
|
int is_root_ref(const char *refname)
|
||||||
{
|
{
|
||||||
static const char *const irregular_pseudorefs[] = {
|
static const char *const irregular_root_refs[] = {
|
||||||
|
"HEAD",
|
||||||
"AUTO_MERGE",
|
"AUTO_MERGE",
|
||||||
"BISECT_EXPECTED_REV",
|
"BISECT_EXPECTED_REV",
|
||||||
"NOTES_MERGE_PARTIAL",
|
"NOTES_MERGE_PARTIAL",
|
||||||
"NOTES_MERGE_REF",
|
"NOTES_MERGE_REF",
|
||||||
"MERGE_AUTOSTASH",
|
"MERGE_AUTOSTASH",
|
||||||
};
|
};
|
||||||
struct object_id oid;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (!is_pseudoref_syntax(refname))
|
if (!is_root_ref_syntax(refname) ||
|
||||||
|
is_pseudo_ref(refname))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ends_with(refname, "_HEAD")) {
|
if (ends_with(refname, "_HEAD"))
|
||||||
refs_resolve_ref_unsafe(refs, refname,
|
return 1;
|
||||||
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
|
|
||||||
&oid, NULL);
|
|
||||||
return !is_null_oid(&oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
|
for (i = 0; i < ARRAY_SIZE(irregular_root_refs); i++)
|
||||||
if (!strcmp(refname, irregular_pseudorefs[i])) {
|
if (!strcmp(refname, irregular_root_refs[i]))
|
||||||
refs_resolve_ref_unsafe(refs, refname,
|
return 1;
|
||||||
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
|
|
||||||
&oid, NULL);
|
|
||||||
return !is_null_oid(&oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_headref(struct ref_store *refs, const char *refname)
|
|
||||||
{
|
|
||||||
if (!strcmp(refname, "HEAD"))
|
|
||||||
return refs_ref_exists(refs, refname);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_current_worktree_ref(const char *ref) {
|
static int is_current_worktree_ref(const char *ref) {
|
||||||
return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
|
return is_root_ref_syntax(ref) || is_per_worktree_ref(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
|
enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
|
||||||
@ -1243,6 +1239,13 @@ int ref_transaction_update(struct ref_transaction *transaction,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
|
||||||
|
is_pseudo_ref(refname)) {
|
||||||
|
strbuf_addf(err, _("refusing to update pseudoref '%s'"),
|
||||||
|
refname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
|
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
|
||||||
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
|
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
|
||||||
|
|
||||||
@ -1816,43 +1819,12 @@ done:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_special_ref(const char *refname)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Special references are refs that have different semantics compared
|
|
||||||
* to "normal" refs. These refs can thus not be stored in the ref
|
|
||||||
* backend, but must always be accessed via the filesystem. The
|
|
||||||
* following refs are special:
|
|
||||||
*
|
|
||||||
* - FETCH_HEAD may contain multiple object IDs, and each one of them
|
|
||||||
* carries additional metadata like where it came from.
|
|
||||||
*
|
|
||||||
* - MERGE_HEAD may contain multiple object IDs when merging multiple
|
|
||||||
* heads.
|
|
||||||
*
|
|
||||||
* Reading, writing or deleting references must consistently go either
|
|
||||||
* through the filesystem (special refs) or through the reference
|
|
||||||
* backend (normal ones).
|
|
||||||
*/
|
|
||||||
static const char * const special_refs[] = {
|
|
||||||
"FETCH_HEAD",
|
|
||||||
"MERGE_HEAD",
|
|
||||||
};
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(special_refs); i++)
|
|
||||||
if (!strcmp(refname, special_refs[i]))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
|
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
|
||||||
struct object_id *oid, struct strbuf *referent,
|
struct object_id *oid, struct strbuf *referent,
|
||||||
unsigned int *type, int *failure_errno)
|
unsigned int *type, int *failure_errno)
|
||||||
{
|
{
|
||||||
assert(failure_errno);
|
assert(failure_errno);
|
||||||
if (is_special_ref(refname))
|
if (is_pseudo_ref(refname))
|
||||||
return refs_read_special_head(ref_store, refname, oid, referent,
|
return refs_read_special_head(ref_store, refname, oid, referent,
|
||||||
type, failure_errno);
|
type, failure_errno);
|
||||||
|
|
||||||
|
48
refs.h
48
refs.h
@ -1013,8 +1013,52 @@ extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];
|
|||||||
*/
|
*/
|
||||||
void update_ref_namespace(enum ref_namespace namespace, char *ref);
|
void update_ref_namespace(enum ref_namespace namespace, char *ref);
|
||||||
|
|
||||||
int is_pseudoref(struct ref_store *refs, const char *refname);
|
/*
|
||||||
int is_headref(struct ref_store *refs, const char *refname);
|
* Check whether the provided name names a root reference. This function only
|
||||||
|
* performs a syntactic check.
|
||||||
|
*
|
||||||
|
* A root ref is a reference that lives in the root of the reference hierarchy.
|
||||||
|
* These references must conform to special syntax:
|
||||||
|
*
|
||||||
|
* - Their name must be all-uppercase or underscores ("_").
|
||||||
|
*
|
||||||
|
* - Their name must end with "_HEAD". As a special rule, "HEAD" is a root
|
||||||
|
* ref, as well.
|
||||||
|
*
|
||||||
|
* - Their name may not contain a slash.
|
||||||
|
*
|
||||||
|
* There is a special set of irregular root refs that exist due to historic
|
||||||
|
* reasons, only. This list shall not be expanded in the future:
|
||||||
|
*
|
||||||
|
* - AUTO_MERGE
|
||||||
|
*
|
||||||
|
* - BISECT_EXPECTED_REV
|
||||||
|
*
|
||||||
|
* - NOTES_MERGE_PARTIAL
|
||||||
|
*
|
||||||
|
* - NOTES_MERGE_REF
|
||||||
|
*
|
||||||
|
* - MERGE_AUTOSTASH
|
||||||
|
*/
|
||||||
|
int is_root_ref(const char *refname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pseudorefs are refs that have different semantics compared to
|
||||||
|
* "normal" refs. These refs can thus not be stored in the ref backend,
|
||||||
|
* but must always be accessed via the filesystem. The following refs
|
||||||
|
* are pseudorefs:
|
||||||
|
*
|
||||||
|
* - FETCH_HEAD may contain multiple object IDs, and each one of them
|
||||||
|
* carries additional metadata like where it came from.
|
||||||
|
*
|
||||||
|
* - MERGE_HEAD may contain multiple object IDs when merging multiple
|
||||||
|
* heads.
|
||||||
|
*
|
||||||
|
* Reading, writing or deleting references must consistently go either
|
||||||
|
* through the filesystem (pseudorefs) or through the reference
|
||||||
|
* backend (normal ones).
|
||||||
|
*/
|
||||||
|
int is_pseudo_ref(const char *refname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following functions have been removed in Git v2.45 in favor of functions
|
* The following functions have been removed in Git v2.45 in favor of functions
|
||||||
|
@ -351,8 +351,7 @@ static void add_pseudoref_and_head_entries(struct ref_store *ref_store,
|
|||||||
strbuf_addstr(&refname, de->d_name);
|
strbuf_addstr(&refname, de->d_name);
|
||||||
|
|
||||||
dtype = get_dtype(de, &path, 1);
|
dtype = get_dtype(de, &path, 1);
|
||||||
if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) ||
|
if (dtype == DT_REG && is_root_ref(de->d_name))
|
||||||
is_headref(ref_store, de->d_name)))
|
|
||||||
loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
|
loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
|
||||||
|
|
||||||
strbuf_setlen(&refname, dirnamelen);
|
strbuf_setlen(&refname, dirnamelen);
|
||||||
|
@ -354,8 +354,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||||||
*/
|
*/
|
||||||
if (!starts_with(iter->ref.refname, "refs/") &&
|
if (!starts_with(iter->ref.refname, "refs/") &&
|
||||||
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
|
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
|
||||||
(is_pseudoref(&iter->refs->base, iter->ref.refname) ||
|
is_root_ref(iter->ref.refname))) {
|
||||||
is_headref(&iter->refs->base, iter->ref.refname)))) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '
|
|||||||
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
|
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
|
||||||
one_head=$(cd one && git rev-parse HEAD) &&
|
one_head=$(cd one && git rev-parse HEAD) &&
|
||||||
this_head=$(git rev-parse HEAD) &&
|
this_head=$(git rev-parse HEAD) &&
|
||||||
git update-ref -d FETCH_HEAD &&
|
rm .git/FETCH_HEAD &&
|
||||||
git fetch one &&
|
git fetch one &&
|
||||||
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
||||||
test $this_head = "$(git rev-parse --verify HEAD)"
|
test $this_head = "$(git rev-parse --verify HEAD)"
|
||||||
@ -530,7 +530,7 @@ test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge
|
|||||||
one_ref=$(cd one && git symbolic-ref HEAD) &&
|
one_ref=$(cd one && git symbolic-ref HEAD) &&
|
||||||
git config branch.main.remote blub &&
|
git config branch.main.remote blub &&
|
||||||
git config branch.main.merge "$one_ref" &&
|
git config branch.main.merge "$one_ref" &&
|
||||||
git update-ref -d FETCH_HEAD &&
|
rm .git/FETCH_HEAD &&
|
||||||
git fetch one &&
|
git fetch one &&
|
||||||
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
||||||
test $this_head = "$(git rev-parse --verify HEAD)"
|
test $this_head = "$(git rev-parse --verify HEAD)"
|
||||||
@ -540,7 +540,7 @@ test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge
|
|||||||
# the merge spec does not match the branch the remote HEAD points to
|
# the merge spec does not match the branch the remote HEAD points to
|
||||||
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
|
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
|
||||||
git config branch.main.merge "${one_ref}_not" &&
|
git config branch.main.merge "${one_ref}_not" &&
|
||||||
git update-ref -d FETCH_HEAD &&
|
rm .git/FETCH_HEAD &&
|
||||||
git fetch one &&
|
git fetch one &&
|
||||||
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
|
||||||
test $this_head = "$(git rev-parse --verify HEAD)"
|
test $this_head = "$(git rev-parse --verify HEAD)"
|
||||||
|
@ -52,6 +52,23 @@ test_expect_success '--include-root-refs pattern prints pseudorefs' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--include-root-refs pattern does not print special refs' '
|
||||||
|
test_when_finished "rm -rf repo" &&
|
||||||
|
git init repo &&
|
||||||
|
(
|
||||||
|
cd repo &&
|
||||||
|
test_commit initial &&
|
||||||
|
git rev-parse HEAD >.git/MERGE_HEAD &&
|
||||||
|
git for-each-ref --format="%(refname)" --include-root-refs >actual &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
HEAD
|
||||||
|
$(git symbolic-ref HEAD)
|
||||||
|
refs/tags/initial
|
||||||
|
EOF
|
||||||
|
test_cmp expect actual
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success '--include-root-refs with other patterns' '
|
test_expect_success '--include-root-refs with other patterns' '
|
||||||
cat >expect <<-\EOF &&
|
cat >expect <<-\EOF &&
|
||||||
HEAD
|
HEAD
|
||||||
@ -62,6 +79,23 @@ test_expect_success '--include-root-refs with other patterns' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--include-root-refs omits dangling symrefs' '
|
||||||
|
test_when_finished "rm -rf repo" &&
|
||||||
|
git init repo &&
|
||||||
|
(
|
||||||
|
cd repo &&
|
||||||
|
test_commit initial &&
|
||||||
|
git symbolic-ref DANGLING_HEAD refs/heads/missing &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
HEAD
|
||||||
|
$(git symbolic-ref HEAD)
|
||||||
|
refs/tags/initial
|
||||||
|
EOF
|
||||||
|
git for-each-ref --format="%(refname)" --include-root-refs >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'filtering with --points-at' '
|
test_expect_success 'filtering with --points-at' '
|
||||||
cat >expect <<-\EOF &&
|
cat >expect <<-\EOF &&
|
||||||
refs/heads/main
|
refs/heads/main
|
||||||
|
Loading…
Reference in New Issue
Block a user