Skip to content

Commit 0845122

Browse files
dturner-twpeff
authored andcommitted
refs: break out ref conflict checks
Create new function find_descendant_ref, to hold one of the ref conflict checks used in verify_refname_available. Multiple backends will need this function, so move it to the common code. Also move rename_ref_available to the common code, because alternate backends might need it and it has no files-backend-specific code. Signed-off-by: David Turner <[email protected]> Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Jeff King <[email protected]>
1 parent 5f3c3a4 commit 0845122

File tree

3 files changed

+67
-42
lines changed

3 files changed

+67
-42
lines changed

refs.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,3 +1029,47 @@ int ref_is_hidden(const char *refname)
10291029
}
10301030
return 0;
10311031
}
1032+
1033+
const char *find_descendant_ref(const char *dirname,
1034+
const struct string_list *extras,
1035+
const struct string_list *skip)
1036+
{
1037+
int pos;
1038+
1039+
if (!extras)
1040+
return NULL;
1041+
1042+
/*
1043+
* Look at the place where dirname would be inserted into
1044+
* extras. If there is an entry at that position that starts
1045+
* with dirname (remember, dirname includes the trailing
1046+
* slash) and is not in skip, then we have a conflict.
1047+
*/
1048+
for (pos = string_list_find_insert_index(extras, dirname, 0);
1049+
pos < extras->nr; pos++) {
1050+
const char *extra_refname = extras->items[pos].string;
1051+
1052+
if (!starts_with(extra_refname, dirname))
1053+
break;
1054+
1055+
if (!skip || !string_list_has_string(skip, extra_refname))
1056+
return extra_refname;
1057+
}
1058+
return NULL;
1059+
}
1060+
1061+
int rename_ref_available(const char *oldname, const char *newname)
1062+
{
1063+
struct string_list skip = STRING_LIST_INIT_NODUP;
1064+
struct strbuf err = STRBUF_INIT;
1065+
int ret;
1066+
1067+
string_list_insert(&skip, oldname);
1068+
ret = !verify_refname_available(newname, NULL, &skip, &err);
1069+
if (!ret)
1070+
error("%s", err.buf);
1071+
1072+
string_list_clear(&skip, 0);
1073+
strbuf_release(&err);
1074+
return ret;
1075+
}

refs/files-backend.c

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ static int verify_refname_available_dir(const char *refname,
728728
struct strbuf *err)
729729
{
730730
const char *slash;
731+
const char *extra_refname;
731732
int pos;
732733
struct strbuf dirname = STRBUF_INIT;
733734
int ret = -1;
@@ -833,32 +834,12 @@ static int verify_refname_available_dir(const char *refname,
833834
}
834835
}
835836

836-
if (extras) {
837-
/*
838-
* Check for entries in extras that start with
839-
* "$refname/". We do that by looking for the place
840-
* where "$refname/" would be inserted in extras. If
841-
* there is an entry at that position that starts with
842-
* "$refname/" and is not in skip, then we have a
843-
* conflict.
844-
*/
845-
for (pos = string_list_find_insert_index(extras, dirname.buf, 0);
846-
pos < extras->nr; pos++) {
847-
const char *extra_refname = extras->items[pos].string;
848-
849-
if (!starts_with(extra_refname, dirname.buf))
850-
break;
851-
852-
if (!skip || !string_list_has_string(skip, extra_refname)) {
853-
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
854-
refname, extra_refname);
855-
goto cleanup;
856-
}
857-
}
858-
}
859-
860-
/* No conflicts were found */
861-
ret = 0;
837+
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
838+
if (extra_refname)
839+
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
840+
refname, extra_refname);
841+
else
842+
ret = 0;
862843

863844
cleanup:
864845
strbuf_release(&dirname);
@@ -2473,22 +2454,6 @@ int verify_refname_available(const char *newname,
24732454
return 0;
24742455
}
24752456

2476-
static int rename_ref_available(const char *oldname, const char *newname)
2477-
{
2478-
struct string_list skip = STRING_LIST_INIT_NODUP;
2479-
struct strbuf err = STRBUF_INIT;
2480-
int ret;
2481-
2482-
string_list_insert(&skip, oldname);
2483-
ret = !verify_refname_available(newname, NULL, &skip, &err);
2484-
if (!ret)
2485-
error("%s", err.buf);
2486-
2487-
string_list_clear(&skip, 0);
2488-
strbuf_release(&err);
2489-
return ret;
2490-
}
2491-
24922457
static int write_ref_to_lockfile(struct ref_lock *lock,
24932458
const unsigned char *sha1, struct strbuf *err);
24942459
static int commit_ref_update(struct ref_lock *lock,

refs/refs-internal.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,20 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1,
181181
const unsigned char *new_sha1, const char *msg,
182182
int flags, struct strbuf *err);
183183

184+
/*
185+
* Check for entries in extras that are within the specified
186+
* directory, where dirname is a reference directory name including
187+
* the trailing slash (e.g., "refs/heads/foo/"). Ignore any
188+
* conflicting references that are found in skip. If there is a
189+
* conflicting reference, return its name.
190+
*
191+
* extras and skip must be sorted lists of reference names. Either one
192+
* can be NULL, signifying the empty list.
193+
*/
194+
const char *find_descendant_ref(const char *dirname,
195+
const struct string_list *extras,
196+
const struct string_list *skip);
197+
198+
int rename_ref_available(const char *oldname, const char *newname);
199+
184200
#endif /* REFS_REFS_INTERNAL_H */

0 commit comments

Comments
 (0)