Skip to content

Commit 8d6413a

Browse files
committed
Merge branch 'ps/refname-avail-check-optim'
The code paths to check whether a refname X is available (by seeing if another ref X/Y exists, etc.) have been optimized. * ps/refname-avail-check-optim: refs: reuse iterators when determining refname availability refs/iterator: implement seeking for files iterators refs/iterator: implement seeking for packed-ref iterators refs/iterator: implement seeking for ref-cache iterators refs/iterator: implement seeking for reftable iterators refs/iterator: implement seeking for merged iterators refs/iterator: provide infrastructure to re-seek iterators refs/iterator: separate lifecycle from iteration refs: stop re-verifying common prefixes for availability refs/files: batch refname availability checks for initial transactions refs/files: batch refname availability checks for normal transactions refs/reftable: batch refname availability checks refs: introduce function to batch refname availability checks builtin/update-ref: skip ambiguity checks when parsing object IDs object-name: allow skipping ambiguity checks in `get_oid()` family object-name: introduce `repo_get_oid_with_flags()`
2 parents 01d17c0 + 87d297f commit 8d6413a

18 files changed

+544
-361
lines changed

builtin/clone.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
342342
strbuf_setlen(src, src_len);
343343
die(_("failed to iterate over '%s'"), src->buf);
344344
}
345+
346+
dir_iterator_free(iter);
345347
}
346348

347349
static void clone_local(const char *src_repo, const char *dest_repo)

builtin/update-ref.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ static int parse_next_oid(const char **next, const char *end,
179179
(*next)++;
180180
*next = parse_arg(*next, &arg);
181181
if (arg.len) {
182-
if (repo_get_oid(the_repository, arg.buf, oid))
182+
if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
183+
GET_OID_SKIP_AMBIGUITY_CHECK))
183184
goto invalid;
184185
} else {
185186
/* Without -z, an empty value means all zeros: */
@@ -197,7 +198,8 @@ static int parse_next_oid(const char **next, const char *end,
197198
*next += arg.len;
198199

199200
if (arg.len) {
200-
if (repo_get_oid(the_repository, arg.buf, oid))
201+
if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
202+
GET_OID_SKIP_AMBIGUITY_CHECK))
201203
goto invalid;
202204
} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
203205
/* With -z, treat an empty value as all zeros: */
@@ -299,7 +301,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction,
299301
die("symref-update %s: expected old value", refname);
300302

301303
if (!strcmp(old_arg, "oid")) {
302-
if (repo_get_oid(the_repository, old_target, &old_oid))
304+
if (repo_get_oid_with_flags(the_repository, old_target, &old_oid,
305+
GET_OID_SKIP_AMBIGUITY_CHECK))
303306
die("symref-update %s: invalid oid: %s", refname, old_target);
304307

305308
have_old_oid = 1;
@@ -772,7 +775,8 @@ int cmd_update_ref(int argc,
772775
refname = argv[0];
773776
value = argv[1];
774777
oldval = argv[2];
775-
if (repo_get_oid(the_repository, value, &oid))
778+
if (repo_get_oid_with_flags(the_repository, value, &oid,
779+
GET_OID_SKIP_AMBIGUITY_CHECK))
776780
die("%s: not a valid SHA1", value);
777781
}
778782

@@ -783,7 +787,8 @@ int cmd_update_ref(int argc,
783787
* must not already exist:
784788
*/
785789
oidclr(&oldoid, the_repository->hash_algo);
786-
else if (repo_get_oid(the_repository, oldval, &oldoid))
790+
else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid,
791+
GET_OID_SKIP_AMBIGUITY_CHECK))
787792
die("%s: not a valid old SHA1", oldval);
788793
}
789794

dir-iterator.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
193193

194194
if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) {
195195
if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC)
196-
goto error_out;
196+
return ITER_ERROR;
197197
if (iter->levels_nr == 0)
198-
goto error_out;
198+
return ITER_ERROR;
199199
}
200200

201201
/* Loop until we find an entry that we can give back to the caller. */
@@ -211,19 +211,19 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
211211
int ret = next_directory_entry(level->dir, iter->base.path.buf, &de);
212212
if (ret < 0) {
213213
if (iter->flags & DIR_ITERATOR_PEDANTIC)
214-
goto error_out;
214+
return ITER_ERROR;
215215
continue;
216216
} else if (ret > 0) {
217217
if (pop_level(iter) == 0)
218-
return dir_iterator_abort(dir_iterator);
218+
return ITER_DONE;
219219
continue;
220220
}
221221

222222
name = de->d_name;
223223
} else {
224224
if (level->entries_idx >= level->entries.nr) {
225225
if (pop_level(iter) == 0)
226-
return dir_iterator_abort(dir_iterator);
226+
return ITER_DONE;
227227
continue;
228228
}
229229

@@ -232,22 +232,21 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
232232

233233
if (prepare_next_entry_data(iter, name)) {
234234
if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC)
235-
goto error_out;
235+
return ITER_ERROR;
236236
continue;
237237
}
238238

239239
return ITER_OK;
240240
}
241-
242-
error_out:
243-
dir_iterator_abort(dir_iterator);
244-
return ITER_ERROR;
245241
}
246242

247-
int dir_iterator_abort(struct dir_iterator *dir_iterator)
243+
void dir_iterator_free(struct dir_iterator *dir_iterator)
248244
{
249245
struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator;
250246

247+
if (!iter)
248+
return;
249+
251250
for (; iter->levels_nr; iter->levels_nr--) {
252251
struct dir_iterator_level *level =
253252
&iter->levels[iter->levels_nr - 1];
@@ -266,7 +265,6 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator)
266265
free(iter->levels);
267266
strbuf_release(&iter->base.path);
268267
free(iter);
269-
return ITER_DONE;
270268
}
271269

272270
struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
@@ -301,7 +299,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
301299
return dir_iterator;
302300

303301
error_out:
304-
dir_iterator_abort(dir_iterator);
302+
dir_iterator_free(dir_iterator);
305303
errno = saved_errno;
306304
return NULL;
307305
}

dir-iterator.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*
2929
* while ((ok = dir_iterator_advance(iter)) == ITER_OK) {
3030
* if (want_to_stop_iteration()) {
31-
* ok = dir_iterator_abort(iter);
31+
* ok = ITER_DONE;
3232
* break;
3333
* }
3434
*
@@ -39,6 +39,7 @@
3939
*
4040
* if (ok != ITER_DONE)
4141
* handle_error();
42+
* dir_iterator_free(iter);
4243
*
4344
* Callers are allowed to modify iter->path while they are working,
4445
* but they must restore it to its original contents before calling
@@ -107,11 +108,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags);
107108
*/
108109
int dir_iterator_advance(struct dir_iterator *iterator);
109110

110-
/*
111-
* End the iteration before it has been exhausted. Free the
112-
* dir_iterator and any associated resources and return ITER_DONE. On
113-
* error, free the dir_iterator and return ITER_ERROR.
114-
*/
115-
int dir_iterator_abort(struct dir_iterator *iterator);
111+
/* Free the dir_iterator and any associated resources. */
112+
void dir_iterator_free(struct dir_iterator *iterator);
116113

117114
#endif

hash.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,17 +193,18 @@ struct object_id {
193193
int algo; /* XXX requires 4-byte alignment */
194194
};
195195

196-
#define GET_OID_QUIETLY 01
197-
#define GET_OID_COMMIT 02
198-
#define GET_OID_COMMITTISH 04
199-
#define GET_OID_TREE 010
200-
#define GET_OID_TREEISH 020
201-
#define GET_OID_BLOB 040
202-
#define GET_OID_FOLLOW_SYMLINKS 0100
203-
#define GET_OID_RECORD_PATH 0200
204-
#define GET_OID_ONLY_TO_DIE 04000
205-
#define GET_OID_REQUIRE_PATH 010000
206-
#define GET_OID_HASH_ANY 020000
196+
#define GET_OID_QUIETLY 01
197+
#define GET_OID_COMMIT 02
198+
#define GET_OID_COMMITTISH 04
199+
#define GET_OID_TREE 010
200+
#define GET_OID_TREEISH 020
201+
#define GET_OID_BLOB 040
202+
#define GET_OID_FOLLOW_SYMLINKS 0100
203+
#define GET_OID_RECORD_PATH 0200
204+
#define GET_OID_ONLY_TO_DIE 04000
205+
#define GET_OID_REQUIRE_PATH 010000
206+
#define GET_OID_HASH_ANY 020000
207+
#define GET_OID_SKIP_AMBIGUITY_CHECK 040000
207208

208209
#define GET_OID_DISAMBIGUATORS \
209210
(GET_OID_COMMIT | GET_OID_COMMITTISH | \

iterator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#define ITER_OK 0
1313

1414
/*
15-
* The iterator is exhausted and has been freed.
15+
* The iterator is exhausted.
1616
*/
1717
#define ITER_DONE -1
1818

object-name.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
961961
int fatal = !(flags & GET_OID_QUIETLY);
962962

963963
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
964-
if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {
964+
if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) &&
965+
repo_settings_get_warn_ambiguous_refs(r) &&
966+
warn_on_object_refname_ambiguity) {
965967
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
966968
if (refs_found > 0) {
967969
warning(warn_msg, len, str);
@@ -1794,18 +1796,20 @@ void object_context_release(struct object_context *ctx)
17941796
strbuf_release(&ctx->symlink_path);
17951797
}
17961798

1797-
/*
1798-
* This is like "get_oid_basic()", except it allows "object ID expressions",
1799-
* notably "xyz^" for "parent of xyz"
1800-
*/
1801-
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
1799+
int repo_get_oid_with_flags(struct repository *r, const char *name,
1800+
struct object_id *oid, unsigned flags)
18021801
{
18031802
struct object_context unused;
1804-
int ret = get_oid_with_context(r, name, 0, oid, &unused);
1803+
int ret = get_oid_with_context(r, name, flags, oid, &unused);
18051804
object_context_release(&unused);
18061805
return ret;
18071806
}
18081807

1808+
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
1809+
{
1810+
return repo_get_oid_with_flags(r, name, oid, 0);
1811+
}
1812+
18091813
/*
18101814
* This returns a non-zero value if the string (built using printf
18111815
* format and the given arguments) is not a valid object.

object-name.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
5151
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
5252
int abbrev_len);
5353

54+
/*
55+
* This is like "get_oid_basic()", except it allows "object ID expressions",
56+
* notably "xyz^" for "parent of xyz". Accepts GET_OID_* flags.
57+
*/
58+
int repo_get_oid_with_flags(struct repository *r, const char *str,
59+
struct object_id *oid, unsigned flags);
5460
int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
5561
__attribute__((format (printf, 2, 3)))
5662
int get_oidf(struct object_id *oid, const char *fmt, ...);

0 commit comments

Comments
 (0)