aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--Documentation/RelNotes/2.47.0.txt9
-rw-r--r--Documentation/technical/sparse-checkout.txt2
-rw-r--r--Makefile8
-rw-r--r--apply.c449
-rw-r--r--builtin/help.c2
-rw-r--r--builtin/ls-files.c2
-rw-r--r--builtin/name-rev.c2
-rw-r--r--builtin/receive-pack.c20
-rw-r--r--config.mak.dev2
-rw-r--r--contrib/buildsystems/CMakeLists.txt25
-rw-r--r--diff.c1
-rw-r--r--diffcore-rename.c4
-rw-r--r--fsmonitor-settings.c2
-rwxr-xr-xgit-instaweb.sh2
-rwxr-xr-xgit-p4.py4
-rw-r--r--gpg-interface.c2
-rw-r--r--http.c2
-rw-r--r--merge-ll.c2
-rw-r--r--merge-ort.c4
-rw-r--r--object-file.c2
-rw-r--r--pretty.c2
-rw-r--r--read-cache-ll.h2
-rw-r--r--rebase.c2
-rw-r--r--ref-filter.c2
-rw-r--r--refs.c35
-rw-r--r--refs.h15
-rw-r--r--refs/reftable-backend.c133
-rw-r--r--reftable/reader.c1
-rw-r--r--revision.h2
-rw-r--r--run-command.h2
-rw-r--r--setup.c2
-rw-r--r--sideband.c2
-rwxr-xr-xt/t1419-exclude-refs.sh49
-rwxr-xr-xt/t3436-rebase-more-options.sh1
-rwxr-xr-xt/t4017-diff-retval.sh8
-rwxr-xr-xt/t4107-apply-ignore-whitespace.sh4
-rwxr-xr-xt/t4124-apply-ws-rule.sh1
-rwxr-xr-xt/t4125-apply-ws-fuzz.sh1
-rwxr-xr-xt/t4138-apply-ws-expansion.sh1
-rwxr-xr-xt/t5509-fetch-push-namespaces.sh9
-rw-r--r--t/unit-tests/lib-reftable.c93
-rw-r--r--t/unit-tests/lib-reftable.h20
-rw-r--r--t/unit-tests/t-reftable-merged.c163
-rw-r--r--t/unit-tests/t-reftable-reader.c96
-rw-r--r--t/unit-tests/t-reftable-readwrite.c130
-rw-r--r--t/unit-tests/t-reftable-stack.c25
-rw-r--r--trace2.h1
-rw-r--r--trace2/tr2_ctr.c5
-rw-r--r--upload-pack.c2
51 files changed, 862 insertions, 497 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 77346a4929..1fbdc2652b 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -9,7 +9,7 @@ freebsd_task:
DEFAULT_TEST_TARGET: prove
DEVELOPER: 1
freebsd_instance:
- image_family: freebsd-13-2
+ image_family: freebsd-13-4
memory: 2G
install_script:
pkg install -y gettext gmake perl5
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 80b1668ebe..4abfbc3e20 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,6 +9,8 @@ workflow:
test:linux:
image: $image
+ tags:
+ - saas-linux-medium-amd64
variables:
CUSTOM_PATH: "/custom"
before_script:
diff --git a/Documentation/RelNotes/2.47.0.txt b/Documentation/RelNotes/2.47.0.txt
index a6c1d4d78d..41ba7cfd91 100644
--- a/Documentation/RelNotes/2.47.0.txt
+++ b/Documentation/RelNotes/2.47.0.txt
@@ -149,6 +149,13 @@ Performance, Internal Implementation, Development Support etc.
been updated to pass the repository, if known, together with the
prefix value.
+ * "git apply" had custom buffer management code that predated before
+ use of strbuf got widespread, which has been updated to use strbuf,
+ which also plugged some memory leaks.
+
+ * The reftable backend learned to more efficiently handle exclude
+ patterns while enumerating the refs.
+
Fixes since v2.46
-----------------
@@ -284,3 +291,5 @@ Fixes since v2.46
(merge 4460e052e0 jc/range-diff-lazy-setup later to maint).
(merge 0627c58e7a ak/typofixes later to maint).
(merge 83799f1500 jk/t9001-deflake later to maint).
+ (merge e02cc08a88 ak/typofix-2.46-maint later to maint).
+ (merge 5c5d29e1c4 ps/ci-gitlab-upgrade later to maint).
diff --git a/Documentation/technical/sparse-checkout.txt b/Documentation/technical/sparse-checkout.txt
index fa0d01cbda..d968659354 100644
--- a/Documentation/technical/sparse-checkout.txt
+++ b/Documentation/technical/sparse-checkout.txt
@@ -287,7 +287,7 @@ everything behaves like a dense checkout with a few exceptions (e.g. branch
checkouts and switches write fewer things, knowing the VFS will lazily
write the rest on an as-needed basis).
-Since there is no publically available VFS-related code for folks to try,
+Since there is no publicly available VFS-related code for folks to try,
the number of folks who can test such a usecase is limited.
The primary reason to note the Behavior C usecase is that as we fix things
diff --git a/Makefile b/Makefile
index 9cf2be070f..7344a7f725 100644
--- a/Makefile
+++ b/Makefile
@@ -1356,6 +1356,7 @@ UNIT_TEST_PROGRAMS += t-reftable-basics
UNIT_TEST_PROGRAMS += t-reftable-block
UNIT_TEST_PROGRAMS += t-reftable-merged
UNIT_TEST_PROGRAMS += t-reftable-pq
+UNIT_TEST_PROGRAMS += t-reftable-reader
UNIT_TEST_PROGRAMS += t-reftable-readwrite
UNIT_TEST_PROGRAMS += t-reftable-record
UNIT_TEST_PROGRAMS += t-reftable-stack
@@ -1365,9 +1366,9 @@ UNIT_TEST_PROGRAMS += t-strcmp-offset
UNIT_TEST_PROGRAMS += t-trailer
UNIT_TEST_PROGRAMS += t-urlmatch-normalization
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
-UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o
+UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o
# xdiff and reftable libs may in turn depend on what is in libgit.a
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
@@ -2725,6 +2726,7 @@ OBJECTS += $(FUZZ_OBJS)
OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
OBJECTS += $(UNIT_TEST_OBJS)
OBJECTS += $(CLAR_TEST_OBJS)
+OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
ifndef NO_CURL
OBJECTS += http.o http-walker.o remote-curl.o
@@ -3864,9 +3866,7 @@ $(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS
-Wl,--allow-multiple-definition \
$(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE)
-$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \
- $(UNIT_TEST_DIR)/test-lib.o \
- $(UNIT_TEST_DIR)/lib-oid.o \
+$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_OBJS) \
$(GITLIBS) GIT-LDFLAGS
$(call mkdir_p_parent_template)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
diff --git a/apply.c b/apply.c
index 7b92387f43..a3fc2d5330 100644
--- a/apply.c
+++ b/apply.c
@@ -278,13 +278,26 @@ struct line {
* This represents a "file", which is an array of "lines".
*/
struct image {
- char *buf;
- size_t len;
- size_t nr;
- size_t alloc;
- struct line *line_allocated;
+ struct strbuf buf;
struct line *line;
+ size_t line_nr, line_alloc;
};
+#define IMAGE_INIT { \
+ .buf = STRBUF_INIT, \
+}
+
+static void image_init(struct image *image)
+{
+ struct image empty = IMAGE_INIT;
+ memcpy(image, &empty, sizeof(*image));
+}
+
+static void image_clear(struct image *image)
+{
+ strbuf_release(&image->buf);
+ free(image->line);
+ image_init(image);
+}
static uint32_t hash_line(const char *cp, size_t len)
{
@@ -298,49 +311,13 @@ static uint32_t hash_line(const char *cp, size_t len)
return h;
}
-/*
- * Compare lines s1 of length n1 and s2 of length n2, ignoring
- * whitespace difference. Returns 1 if they match, 0 otherwise
- */
-static int fuzzy_matchlines(const char *s1, size_t n1,
- const char *s2, size_t n2)
+static void image_add_line(struct image *img, const char *bol, size_t len, unsigned flag)
{
- const char *end1 = s1 + n1;
- const char *end2 = s2 + n2;
-
- /* ignore line endings */
- while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
- end1--;
- while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
- end2--;
-
- while (s1 < end1 && s2 < end2) {
- if (isspace(*s1)) {
- /*
- * Skip whitespace. We check on both buffers
- * because we don't want "a b" to match "ab".
- */
- if (!isspace(*s2))
- return 0;
- while (s1 < end1 && isspace(*s1))
- s1++;
- while (s2 < end2 && isspace(*s2))
- s2++;
- } else if (*s1++ != *s2++)
- return 0;
- }
-
- /* If we reached the end on one side only, lines don't match. */
- return s1 == end1 && s2 == end2;
-}
-
-static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)
-{
- ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc);
- img->line_allocated[img->nr].len = len;
- img->line_allocated[img->nr].hash = hash_line(bol, len);
- img->line_allocated[img->nr].flag = flag;
- img->nr++;
+ ALLOC_GROW(img->line, img->line_nr + 1, img->line_alloc);
+ img->line[img->line_nr].len = len;
+ img->line[img->line_nr].hash = hash_line(bol, len);
+ img->line[img->line_nr].flag = flag;
+ img->line_nr++;
}
/*
@@ -348,37 +325,43 @@ static void add_line_info(struct image *img, const char *bol, size_t len, unsign
* attach it to "image" and add line-based index to it.
* "image" now owns the "buf".
*/
-static void prepare_image(struct image *image, char *buf, size_t len,
+static void image_prepare(struct image *image, char *buf, size_t len,
int prepare_linetable)
{
const char *cp, *ep;
- memset(image, 0, sizeof(*image));
- image->buf = buf;
- image->len = len;
+ image_clear(image);
+ strbuf_attach(&image->buf, buf, len, len + 1);
if (!prepare_linetable)
return;
- ep = image->buf + image->len;
- cp = image->buf;
+ ep = image->buf.buf + image->buf.len;
+ cp = image->buf.buf;
while (cp < ep) {
const char *next;
for (next = cp; next < ep && *next != '\n'; next++)
;
if (next < ep)
next++;
- add_line_info(image, cp, next - cp, 0);
+ image_add_line(image, cp, next - cp, 0);
cp = next;
}
- image->line = image->line_allocated;
}
-static void clear_image(struct image *image)
+static void image_remove_first_line(struct image *img)
{
- free(image->buf);
- free(image->line_allocated);
- memset(image, 0, sizeof(*image));
+ strbuf_remove(&img->buf, 0, img->line[0].len);
+ img->line_nr--;
+ if (img->line_nr)
+ MOVE_ARRAY(img->line, img->line + 1, img->line_nr);
+}
+
+static void image_remove_last_line(struct image *img)
+{
+ size_t last_line_len = img->line[img->line_nr - 1].len;
+ strbuf_setlen(&img->buf, img->buf.len - last_line_len);
+ img->line_nr--;
}
/* fmt must contain _one_ %s and no other substitution */
@@ -2327,65 +2310,43 @@ static int read_old_data(struct stat *st, struct patch *patch,
/*
* Update the preimage, and the common lines in postimage,
- * from buffer buf of length len. If postlen is 0 the postimage
- * is updated in place, otherwise it's updated on a new buffer
- * of length postlen
+ * from buffer buf of length len.
*/
-
static void update_pre_post_images(struct image *preimage,
struct image *postimage,
- char *buf,
- size_t len, size_t postlen)
+ char *buf, size_t len)
{
+ struct image fixed_preimage = IMAGE_INIT;
+ size_t insert_pos = 0;
int i, ctx, reduced;
- char *new_buf, *old_buf, *fixed;
- struct image fixed_preimage;
+ const char *fixed;
/*
* Update the preimage with whitespace fixes. Note that we
* are not losing preimage->buf -- apply_one_fragment() will
* free "oldlines".
*/
- prepare_image(&fixed_preimage, buf, len, 1);
- assert(postlen
- ? fixed_preimage.nr == preimage->nr
- : fixed_preimage.nr <= preimage->nr);
- for (i = 0; i < fixed_preimage.nr; i++)
+ image_prepare(&fixed_preimage, buf, len, 1);
+ for (i = 0; i < fixed_preimage.line_nr; i++)
fixed_preimage.line[i].flag = preimage->line[i].flag;
- free(preimage->line_allocated);
+ image_clear(preimage);
*preimage = fixed_preimage;
+ fixed = preimage->buf.buf;
/*
- * Adjust the common context lines in postimage. This can be
- * done in-place when we are shrinking it with whitespace
- * fixing, but needs a new buffer when ignoring whitespace or
- * expanding leading tabs to spaces.
- *
- * We trust the caller to tell us if the update can be done
- * in place (postlen==0) or not.
+ * Adjust the common context lines in postimage.
*/
- old_buf = postimage->buf;
- if (postlen)
- new_buf = postimage->buf = xmalloc(postlen);
- else
- new_buf = old_buf;
- fixed = preimage->buf;
-
- for (i = reduced = ctx = 0; i < postimage->nr; i++) {
+ for (i = reduced = ctx = 0; i < postimage->line_nr; i++) {
size_t l_len = postimage->line[i].len;
+
if (!(postimage->line[i].flag & LINE_COMMON)) {
/* an added line -- no counterparts in preimage */
- memmove(new_buf, old_buf, l_len);
- old_buf += l_len;
- new_buf += l_len;
+ insert_pos += l_len;
continue;
}
- /* a common context -- skip it in the original postimage */
- old_buf += l_len;
-
/* and find the corresponding one in the fixed preimage */
- while (ctx < preimage->nr &&
+ while (ctx < preimage->line_nr &&
!(preimage->line[ctx].flag & LINE_COMMON)) {
fixed += preimage->line[ctx].len;
ctx++;
@@ -2395,29 +2356,59 @@ static void update_pre_post_images(struct image *preimage,
* preimage is expected to run out, if the caller
* fixed addition of trailing blank lines.
*/
- if (preimage->nr <= ctx) {
+ if (preimage->line_nr <= ctx) {
reduced++;
continue;
}
/* and copy it in, while fixing the line length */
l_len = preimage->line[ctx].len;
- memcpy(new_buf, fixed, l_len);
- new_buf += l_len;
+ strbuf_splice(&postimage->buf, insert_pos, postimage->line[i].len,
+ fixed, l_len);
+ insert_pos += l_len;
fixed += l_len;
postimage->line[i].len = l_len;
ctx++;
}
- if (postlen
- ? postlen < new_buf - postimage->buf
- : postimage->len < new_buf - postimage->buf)
- BUG("caller miscounted postlen: asked %d, orig = %d, used = %d",
- (int)postlen, (int) postimage->len, (int)(new_buf - postimage->buf));
-
/* Fix the length of the whole thing */
- postimage->len = new_buf - postimage->buf;
- postimage->nr -= reduced;
+ postimage->line_nr -= reduced;
+}
+
+/*
+ * Compare lines s1 of length n1 and s2 of length n2, ignoring
+ * whitespace difference. Returns 1 if they match, 0 otherwise
+ */
+static int fuzzy_matchlines(const char *s1, size_t n1,
+ const char *s2, size_t n2)
+{
+ const char *end1 = s1 + n1;
+ const char *end2 = s2 + n2;
+
+ /* ignore line endings */
+ while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
+ end1--;
+ while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
+ end2--;
+
+ while (s1 < end1 && s2 < end2) {
+ if (isspace(*s1)) {
+ /*
+ * Skip whitespace. We check on both buffers
+ * because we don't want "a b" to match "ab".
+ */
+ if (!isspace(*s2))
+ return 0;
+ while (s1 < end1 && isspace(*s1))
+ s1++;
+ while (s2 < end2 && isspace(*s2))
+ s2++;
+ } else if (*s1++ != *s2++)
+ return 0;
+ }
+
+ /* If we reached the end on one side only, lines don't match. */
+ return s1 == end1 && s2 == end2;
}
static int line_by_line_fuzzy_match(struct image *img,
@@ -2430,7 +2421,6 @@ static int line_by_line_fuzzy_match(struct image *img,
int i;
size_t imgoff = 0;
size_t preoff = 0;
- size_t postlen = postimage->len;
size_t extra_chars;
char *buf;
char *preimage_eof;
@@ -2443,11 +2433,9 @@ static int line_by_line_fuzzy_match(struct image *img,
size_t prelen = preimage->line[i].len;
size_t imglen = img->line[current_lno+i].len;
- if (!fuzzy_matchlines(img->buf + current + imgoff, imglen,
- preimage->buf + preoff, prelen))
+ if (!fuzzy_matchlines(img->buf.buf + current + imgoff, imglen,
+ preimage->buf.buf + preoff, prelen))
return 0;
- if (preimage->line[i].flag & LINE_COMMON)
- postlen += imglen - prelen;
imgoff += imglen;
preoff += prelen;
}
@@ -2463,10 +2451,10 @@ static int line_by_line_fuzzy_match(struct image *img,
* are whitespace characters. (This can only happen if
* we are removing blank lines at the end of the file.)
*/
- buf = preimage_eof = preimage->buf + preoff;
- for ( ; i < preimage->nr; i++)
+ buf = preimage_eof = preimage->buf.buf + preoff;
+ for ( ; i < preimage->line_nr; i++)
preoff += preimage->line[i].len;
- preimage_end = preimage->buf + preoff;
+ preimage_end = preimage->buf.buf + preoff;
for ( ; buf < preimage_end; buf++)
if (!isspace(*buf))
return 0;
@@ -2480,11 +2468,11 @@ static int line_by_line_fuzzy_match(struct image *img,
*/
extra_chars = preimage_end - preimage_eof;
strbuf_init(&fixed, imgoff + extra_chars);
- strbuf_add(&fixed, img->buf + current, imgoff);
+ strbuf_add(&fixed, img->buf.buf + current, imgoff);
strbuf_add(&fixed, preimage_eof, extra_chars);
fixed_buf = strbuf_detach(&fixed, &fixed_len);
update_pre_post_images(preimage, postimage,
- fixed_buf, fixed_len, postlen);
+ fixed_buf, fixed_len);
return 1;
}
@@ -2500,16 +2488,17 @@ static int match_fragment(struct apply_state *state,
int i;
const char *orig, *target;
struct strbuf fixed = STRBUF_INIT;
- size_t postlen;
+ char *fixed_buf;
+ size_t fixed_len;
int preimage_limit;
int ret;
- if (preimage->nr + current_lno <= img->nr) {
+ if (preimage->line_nr + current_lno <= img->line_nr) {
/*
* The hunk falls within the boundaries of img.
*/
- preimage_limit = preimage->nr;
- if (match_end && (preimage->nr + current_lno != img->nr)) {
+ preimage_limit = preimage->line_nr;
+ if (match_end && (preimage->line_nr + current_lno != img->line_nr)) {
ret = 0;
goto out;
}
@@ -2522,7 +2511,7 @@ static int match_fragment(struct apply_state *state,
* match with img, and the remainder of the preimage
* must be blank.
*/
- preimage_limit = img->nr - current_lno;
+ preimage_limit = img->line_nr - current_lno;
} else {
/*
* The hunk extends beyond the end of the img and
@@ -2547,7 +2536,7 @@ static int match_fragment(struct apply_state *state,
}
}
- if (preimage_limit == preimage->nr) {
+ if (preimage_limit == preimage->line_nr) {
/*
* Do we have an exact match? If we were told to match
* at the end, size must be exactly at current+fragsize,
@@ -2556,9 +2545,9 @@ static int match_fragment(struct apply_state *state,
* exactly.
*/
if ((match_end
- ? (current + preimage->len == img->len)
- : (current + preimage->len <= img->len)) &&
- !memcmp(img->buf + current, preimage->buf, preimage->len)) {
+ ? (current + preimage->buf.len == img->buf.len)
+ : (current + preimage->buf.len <= img->buf.len)) &&
+ !memcmp(img->buf.buf + current, preimage->buf.buf, preimage->buf.len)) {
ret = 1;
goto out;
}
@@ -2572,7 +2561,7 @@ static int match_fragment(struct apply_state *state,
*/
const char *buf, *buf_end;
- buf = preimage->buf;
+ buf = preimage->buf.buf;
buf_end = buf;
for (i = 0; i < preimage_limit; i++)
buf_end += preimage->line[i].len;
@@ -2617,21 +2606,14 @@ static int match_fragment(struct apply_state *state,
* fixed.
*/
- /* First count added lines in postimage */
- postlen = 0;
- for (i = 0; i < postimage->nr; i++) {
- if (!(postimage->line[i].flag & LINE_COMMON))
- postlen += postimage->line[i].len;
- }
-
/*
* The preimage may extend beyond the end of the file,
* but in this loop we will only handle the part of the
* preimage that falls within the file.
*/
- strbuf_grow(&fixed, preimage->len + 1);
- orig = preimage->buf;
- target = img->buf + current;
+ strbuf_grow(&fixed, preimage->buf.len + 1);
+ orig = preimage->buf.buf;
+ target = img->buf.buf + current;
for (i = 0; i < preimage_limit; i++) {
size_t oldlen = preimage->line[i].len;
size_t tgtlen = img->line[current_lno + i].len;
@@ -2660,10 +2642,6 @@ static int match_fragment(struct apply_state *state,
!memcmp(tgtfix.buf, fixed.buf + fixstart,
fixed.len - fixstart));
- /* Add the length if this is common with the postimage */
- if (preimage->line[i].flag & LINE_COMMON)
- postlen += tgtfix.len;
-
strbuf_release(&tgtfix);
if (!match) {
ret = 0;
@@ -2681,7 +2659,7 @@ static int match_fragment(struct apply_state *state,
* empty or only contain whitespace (if WS_BLANK_AT_EOL is
* false).
*/
- for ( ; i < preimage->nr; i++) {
+ for ( ; i < preimage->line_nr; i++) {
size_t fixstart = fixed.len; /* start of the fixed preimage */
size_t oldlen = preimage->line[i].len;
int j;
@@ -2705,10 +2683,9 @@ static int match_fragment(struct apply_state *state,
* has whitespace breakages unfixed, and fixing them makes the
* hunk match. Update the context lines in the postimage.
*/
- if (postlen < postimage->len)
- postlen = 0;
+ fixed_buf = strbuf_detach(&fixed, &fixed_len);
update_pre_post_images(preimage, postimage,
- fixed.buf, fixed.len, postlen);
+ fixed_buf, fixed_len);
ret = 1;
@@ -2736,7 +2713,7 @@ static int find_pos(struct apply_state *state,
* than `match_beginning`.
*/
if (state->allow_overlap && match_beginning && match_end &&
- img->nr - preimage->nr != 0)
+ img->line_nr - preimage->line_nr != 0)
match_beginning = 0;
/*
@@ -2747,15 +2724,15 @@ static int find_pos(struct apply_state *state,
if (match_beginning)
line = 0;
else if (match_end)
- line = img->nr - preimage->nr;
+ line = img->line_nr - preimage->line_nr;
/*
* Because the comparison is unsigned, the following test
* will also take care of a negative line number that can
* result when match_end and preimage is larger than the target.
*/
- if ((size_t) line > img->nr)
- line = img->nr;
+ if ((size_t) line > img->line_nr)
+ line = img->line_nr;
current = 0;
for (i = 0; i < line; i++)
@@ -2778,7 +2755,7 @@ static int find_pos(struct apply_state *state,
return current_lno;
again:
- if (backwards_lno == 0 && forwards_lno == img->nr)
+ if (backwards_lno == 0 && forwards_lno == img->line_nr)
break;
if (i & 1) {
@@ -2791,7 +2768,7 @@ static int find_pos(struct apply_state *state,
current = backwards;
current_lno = backwards_lno;
} else {
- if (forwards_lno == img->nr) {
+ if (forwards_lno == img->line_nr) {
i++;
goto again;
}
@@ -2805,19 +2782,6 @@ static int find_pos(struct apply_state *state,
return -1;
}
-static void remove_first_line(struct image *img)
-{
- img->buf += img->line[0].len;
- img->len -= img->line[0].len;
- img->line++;
- img->nr--;
-}
-
-static void remove_last_line(struct image *img)
-{
- img->len -= img->line[--img->nr].len;
-}
-
/*
* The change from "preimage" and "postimage" has been found to
* apply at applied_pos (counts in line numbers) in "img".
@@ -2835,6 +2799,7 @@ static void update_image(struct apply_state *state,
*/
int i, nr;
size_t remove_count, insert_count, applied_at = 0;
+ size_t result_alloc;
char *result;
int preimage_limit;
@@ -2847,9 +2812,9 @@ static void update_image(struct apply_state *state,
* to the number of lines in the preimage that falls
* within the boundaries.
*/
- preimage_limit = preimage->nr;
- if (preimage_limit > img->nr - applied_pos)
- preimage_limit = img->nr - applied_pos;
+ preimage_limit = preimage->line_nr;
+ if (preimage_limit > img->line_nr - applied_pos)
+ preimage_limit = img->line_nr - applied_pos;
for (i = 0; i < applied_pos; i++)
applied_at += img->line[i].len;
@@ -2857,39 +2822,36 @@ static void update_image(struct apply_state *state,
remove_count = 0;
for (i = 0; i < preimage_limit; i++)
remove_count += img->line[applied_pos + i].len;
- insert_count = postimage->len;
+ insert_count = postimage->buf.len;
/* Adjust the contents */
- result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1));
- memcpy(result, img->buf, applied_at);
- memcpy(result + applied_at, postimage->buf, postimage->len);
- memcpy(result + applied_at + postimage->len,
- img->buf + (applied_at + remove_count),
- img->len - (applied_at + remove_count));
- free(img->buf);
- img->buf = result;
- img->len += insert_count - remove_count;
- result[img->len] = '\0';
+ result_alloc = st_add3(st_sub(img->buf.len, remove_count), insert_count, 1);
+ result = xmalloc(result_alloc);
+ memcpy(result, img->buf.buf, applied_at);
+ memcpy(result + applied_at, postimage->buf.buf, postimage->buf.len);
+ memcpy(result + applied_at + postimage->buf.len,
+ img->buf.buf + (applied_at + remove_count),
+ img->buf.len - (applied_at + remove_count));
+ strbuf_attach(&img->buf, result, postimage->buf.len + img->buf.len - remove_count,
+ result_alloc);
/* Adjust the line table */
- nr = img->nr + postimage->nr - preimage_limit;
- if (preimage_limit < postimage->nr) {
+ nr = img->line_nr + postimage->line_nr - preimage_limit;
+ if (preimage_limit < postimage->line_nr)
/*
- * NOTE: this knows that we never call remove_first_line()
+ * NOTE: this knows that we never call image_remove_first_line()
* on anything other than pre/post image.
*/
REALLOC_ARRAY(img->line, nr);
- img->line_allocated = img->line;
- }
- if (preimage_limit != postimage->nr)
- MOVE_ARRAY(img->line + applied_pos + postimage->nr,
+ if (preimage_limit != postimage->line_nr)
+ MOVE_ARRAY(img->line + applied_pos + postimage->line_nr,
img->line + applied_pos + preimage_limit,
- img->nr - (applied_pos + preimage_limit));
- COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->nr);
+ img->line_nr - (applied_pos + preimage_limit));
+ COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->line_nr);
if (!state->allow_overlap)
- for (i = 0; i < postimage->nr; i++)
+ for (i = 0; i < postimage->line_nr; i++)
img->line[applied_pos + i].flag |= LINE_PATCHED;
- img->nr = nr;
+ img->line_nr = nr;
}
/*
@@ -2912,11 +2874,9 @@ static int apply_one_fragment(struct apply_state *state,
int hunk_linenr = frag->linenr;
unsigned long leading, trailing;
int pos, applied_pos;
- struct image preimage;
- struct image postimage;
+ struct image preimage = IMAGE_INIT;
+ struct image postimage = IMAGE_INIT;
- memset(&preimage, 0, sizeof(preimage));
- memset(&postimage, 0, sizeof(postimage));
oldlines = xmalloc(size);
strbuf_init(&newlines, size);
@@ -2958,8 +2918,8 @@ static int apply_one_fragment(struct apply_state *state,
break;
*old++ = '\n';
strbuf_addch(&newlines, '\n');
- add_line_info(&preimage, "\n", 1, LINE_COMMON);
- add_line_info(&postimage, "\n", 1, LINE_COMMON);
+ image_add_line(&preimage, "\n", 1, LINE_COMMON);
+ image_add_line(&postimage, "\n", 1, LINE_COMMON);
is_blank_context = 1;
break;
case ' ':
@@ -2969,7 +2929,7 @@ static int apply_one_fragment(struct apply_state *state,
/* fallthrough */
case '-':
memcpy(old, patch + 1, plen);
- add_line_info(&preimage, old, plen,
+ image_add_line(&preimage, old, plen,
(first == ' ' ? LINE_COMMON : 0));
old += plen;
if (first == '-')
@@ -2989,7 +2949,7 @@ static int apply_one_fragment(struct apply_state *state,
else {
ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws);
}
- add_line_info(&postimage, newlines.buf + start, newlines.len - start,
+ image_add_line(&postimage, newlines.buf + start, newlines.len - start,
(first == '+' ? 0 : LINE_COMMON));
if (first == '+' &&
(ws_rule & WS_BLANK_AT_EOF) &&
@@ -3023,8 +2983,8 @@ static int apply_one_fragment(struct apply_state *state,
newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
old--;
strbuf_setlen(&newlines, newlines.len - 1);
- preimage.line_allocated[preimage.nr - 1].len--;
- postimage.line_allocated[postimage.nr - 1].len--;
+ preimage.line[preimage.line_nr - 1].len--;
+ postimage.line[postimage.line_nr - 1].len--;
}
leading = frag->leading;
@@ -3054,12 +3014,8 @@ static int apply_one_fragment(struct apply_state *state,
match_end = !state->unidiff_zero && !trailing;
pos = frag->newpos ? (frag->newpos - 1) : 0;
- preimage.buf = oldlines;
- preimage.len = old - oldlines;
- postimage.buf = newlines.buf;
- postimage.len = newlines.len;
- preimage.line = preimage.line_allocated;
- postimage.line = postimage.line_allocated;
+ strbuf_add(&preimage.buf, oldlines, old - oldlines);
+ strbuf_swap(&postimage.buf, &newlines);
for (;;) {
@@ -3083,28 +3039,28 @@ static int apply_one_fragment(struct apply_state *state,
* just reduce the larger context.
*/
if (leading >= trailing) {
- remove_first_line(&preimage);
- remove_first_line(&postimage);
+ image_remove_first_line(&preimage);
+ image_remove_first_line(&postimage);
pos--;
leading--;
}
if (trailing > leading) {
- remove_last_line(&preimage);
- remove_last_line(&postimage);
+ image_remove_last_line(&preimage);
+ image_remove_last_line(&postimage);
trailing--;
}
}
if (applied_pos >= 0) {
if (new_blank_lines_at_end &&
- preimage.nr + applied_pos >= img->nr &&
+ preimage.line_nr + applied_pos >= img->line_nr &&
(ws_rule & WS_BLANK_AT_EOF) &&
state->ws_error_action != nowarn_ws_error) {
record_ws_error(state, WS_BLANK_AT_EOF, "+", 1,
found_new_blank_lines_at_end);
if (state->ws_error_action == correct_ws_error) {
while (new_blank_lines_at_end--)
- remove_last_line(&postimage);
+ image_remove_last_line(&postimage);
}
/*
* We would want to prevent write_out_results()
@@ -3147,8 +3103,8 @@ static int apply_one_fragment(struct apply_state *state,
out:
free(oldlines);
strbuf_release(&newlines);
- free(preimage.line_allocated);
- free(postimage.line_allocated);
+ image_clear(&preimage);
+ image_clear(&postimage);
return (applied_pos < 0);
}
@@ -3178,18 +3134,16 @@ static int apply_binary_fragment(struct apply_state *state,
}
switch (fragment->binary_patch_method) {
case BINARY_DELTA_DEFLATED:
- dst = patch_delta(img->buf, img->len, fragment->patch,
+ dst = patch_delta(img->buf.buf, img->buf.len, fragment->patch,
fragment->size, &len);
if (!dst)
return -1;
- clear_image(img);
- img->buf = dst;
- img->len = len;
+ image_clear(img);
+ strbuf_attach(&img->buf, dst, len, len + 1);
return 0;
case BINARY_LITERAL_DEFLATED:
- clear_image(img);
- img->len = fragment->size;
- img->buf = xmemdupz(fragment->patch, img->len);
+ image_clear(img);
+ strbuf_add(&img->buf, fragment->patch, fragment->size);
return 0;
}
return -1;
@@ -3225,8 +3179,8 @@ static int apply_binary(struct apply_state *state,
* See if the old one matches what the patch
* applies to.
*/
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
- &oid);
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len,
+ OBJ_BLOB, &oid);
if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))
return error(_("the patch applies to '%s' (%s), "
"which does not match the "
@@ -3235,14 +3189,14 @@ static int apply_binary(struct apply_state *state,
}
else {
/* Otherwise, the old one must be empty. */
- if (img->len)
+ if (img->buf.len)
return error(_("the patch applies to an empty "
"'%s' but it is not empty"), name);
}
get_oid_hex(patch->new_oid_prefix, &oid);
if (is_null_oid(&oid)) {
- clear_image(img);
+ image_clear(img);
return 0; /* deletion patch */
}
@@ -3258,9 +3212,8 @@ static int apply_binary(struct apply_state *state,
return error(_("the necessary postimage %s for "
"'%s' cannot be read"),
patch->new_oid_prefix, name);
- clear_image(img);
- img->buf = result;
- img->len = size;
+ image_clear(img);
+ strbuf_attach(&img->buf, result, size, size + 1);
} else {
/*
* We have verified buf matches the preimage;
@@ -3272,7 +3225,7 @@ static int apply_binary(struct apply_state *state,
name);
/* verify that the result matches */
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len, OBJ_BLOB,
&oid);
if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))
return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
@@ -3534,7 +3487,7 @@ static int load_preimage(struct apply_state *state,
}
img = strbuf_detach(&buf, &len);
- prepare_image(image, img, len, !patch->is_binary);
+ image_prepare(image, img, len, !patch->is_binary);
return 0;
}
@@ -3542,14 +3495,14 @@ static int resolve_to(struct image *image, const struct object_id *result_id)
{
unsigned long size;
enum object_type type;
+ char *data;
- clear_image(image);
+ image_clear(image);
- image->buf = repo_read_object_file(the_repository, result_id, &type,
- &size);
- if (!image->buf || type != OBJ_BLOB)
+ data = repo_read_object_file(the_repository, result_id, &type, &size);
+ if (!data || type != OBJ_BLOB)
die("unable to read blob object %s", oid_to_hex(result_id));
- image->len = size;
+ strbuf_attach(&image->buf, data, size, size + 1);
return 0;
}
@@ -3592,9 +3545,8 @@ static int three_way_merge(struct apply_state *state,
free(result.ptr);
return -1;
}
- clear_image(image);
- image->buf = result.ptr;
- image->len = result.size;
+ image_clear(image);
+ strbuf_attach(&image->buf, result.ptr, result.size, result.size);
return status;
}
@@ -3639,7 +3591,7 @@ static int load_current(struct apply_state *state,
else if (status)
return -1;
img = strbuf_detach(&buf, &len);
- prepare_image(image, img, len, !patch->is_binary);
+ image_prepare(image, img, len, !patch->is_binary);
return 0;
}
@@ -3654,7 +3606,7 @@ static int try_threeway(struct apply_state *state,
size_t len;
int status;
char *img;
- struct image tmp_image;
+ struct image tmp_image = IMAGE_INIT;
/* No point falling back to 3-way merge in these cases */
if (patch->is_delete ||
@@ -3674,15 +3626,15 @@ static int try_threeway(struct apply_state *state,
fprintf(stderr, _("Performing three-way merge...\n"));
img = strbuf_detach(&buf, &len);
- prepare_image(&tmp_image, img, len, 1);
+ image_prepare(&tmp_image, img, len, 1);
/* Apply the patch to get the post image */
if (apply_fragments(state, &tmp_image, patch) < 0) {
- clear_image(&tmp_image);
+ image_clear(&tmp_image);
return -1;
}
/* post_oid is theirs */
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);
- clear_image(&tmp_image);
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid);
+ image_clear(&tmp_image);
/* our_oid is ours */
if (patch->is_new) {
@@ -3694,8 +3646,8 @@ static int try_threeway(struct apply_state *state,
return error(_("cannot read the current contents of '%s'"),
patch->old_name);
}
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);
- clear_image(&tmp_image);
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid);
+ image_clear(&tmp_image);
/* in-core three-way merge between post and our using pre as base */
status = three_way_merge(state, image, patch->new_name,
@@ -3731,7 +3683,7 @@ static int try_threeway(struct apply_state *state,
static int apply_data(struct apply_state *state, struct patch *patch,
struct stat *st, const struct cache_entry *ce)
{
- struct image image;
+ struct image image = IMAGE_INIT;
if (load_preimage(state, &image, patch, st, ce) < 0)
return -1;
@@ -3743,14 +3695,13 @@ static int apply_data(struct apply_state *state, struct patch *patch,
/* Note: with --reject, apply_fragments() returns 0 */
if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) {
- clear_image(&image);
+ image_clear(&image);
return -1;
}
}
- patch->result = image.buf;
- patch->resultsize = image.len;
+ patch->result = strbuf_detach(&image.buf, &patch->resultsize);
add_to_fn_table(state, patch);
- free(image.line_allocated);
+ free(image.line);
if (0 < patch->is_delete && patch->resultsize)
return error(_("removal patch leaves file contents"));
diff --git a/builtin/help.c b/builtin/help.c
index 9c4cfe11d9..a509241a80 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -542,7 +542,7 @@ static void open_html(const char *path)
static void show_html_page(const char *page)
{
- struct strbuf page_path; /* it leaks but we exec bellow */
+ struct strbuf page_path; /* it leaks but we exec below */
get_html_page_path(&page_path, page);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 6aaba08e30..e016b0415d 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -507,7 +507,7 @@ static int get_common_prefix_len(const char *common_prefix)
common_prefix_len = strlen(common_prefix);
/*
- * If the prefix has a trailing slash, strip it so that submodules wont
+ * If the prefix has a trailing slash, strip it so that submodules won't
* be pruned from the index.
*/
if (common_prefix[common_prefix_len - 1] == '/')
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 7f08c38629..765eb20a93 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -65,7 +65,7 @@ static void set_commit_cutoff(struct commit *commit)
static void adjust_cutoff_timestamp_for_slop(void)
{
if (cutoff) {
- /* check for undeflow */
+ /* check for underflow */
if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
cutoff = cutoff - CUTOFF_DATE_SLOP;
else
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c4b766c613..536d22761d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -340,12 +340,26 @@ static void show_one_alternate_ref(const struct object_id *oid,
static void write_head_info(void)
{
static struct oidset seen = OIDSET_INIT;
+ struct strvec excludes_vector = STRVEC_INIT;
+ const char **exclude_patterns;
+
+ /*
+ * We need access to the reference names both with and without their
+ * namespace and thus cannot use `refs_for_each_namespaced_ref()`. We
+ * thus have to adapt exclude patterns to carry the namespace prefix
+ * ourselves.
+ */
+ exclude_patterns = get_namespaced_exclude_patterns(
+ hidden_refs_to_excludes(&hidden_refs),
+ get_git_namespace(), &excludes_vector);
refs_for_each_fullref_in(get_main_ref_store(the_repository), "",
- hidden_refs_to_excludes(&hidden_refs),
- show_ref_cb, &seen);
+ exclude_patterns, show_ref_cb, &seen);
for_each_alternate_ref(show_one_alternate_ref, &seen);
+
oidset_clear(&seen);
+ strvec_clear(&excludes_vector);
+
if (!sent_capabilities)
show_ref("capabilities^{}", null_oid());
@@ -1325,7 +1339,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
}
/*
- * NEEDSWORK: we should consolidate various implementions of "are we
+ * NEEDSWORK: we should consolidate various implementations of "are we
* on an unborn branch?" test into one, and make the unified one more
* robust. !get_sha1() based check used here and elsewhere would not
* allow us to tell an unborn branch from corrupt ref, for example.
diff --git a/config.mak.dev b/config.mak.dev
index 50026d1e0e..8eca7fa228 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -69,7 +69,7 @@ DEVELOPER_CFLAGS += -Wno-missing-braces
endif
endif
-# Old versions of clang complain about initializaing a
+# Old versions of clang complain about initializing a
# struct-within-a-struct using just "{0}" rather than "{{0}}". This
# error is considered a false-positive and not worth fixing, because
# new clang versions do not, so just disable it.
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 608fd3fe70..62af7b33d2 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -970,18 +970,15 @@ if(BUILD_TESTING)
add_executable(test-fake-ssh ${CMAKE_SOURCE_DIR}/t/helper/test-fake-ssh.c)
target_link_libraries(test-fake-ssh common-main)
-#reftable-tests
-parse_makefile_for_sources(test-reftable_SOURCES "REFTABLE_TEST_OBJS")
-list(TRANSFORM test-reftable_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
-
#unit-tests
-add_library(unit-test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
-add_library(unit-test-lib-oid OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/lib-oid.c)
+parse_makefile_for_sources(unit-test_SOURCES "UNIT_TEST_OBJS")
+list(TRANSFORM unit-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/")
+add_library(unit-test-lib STATIC ${unit-test_SOURCES})
parse_makefile_for_scripts(unit_test_PROGRAMS "UNIT_TEST_PROGRAMS" "")
foreach(unit_test ${unit_test_PROGRAMS})
add_executable("${unit_test}" "${CMAKE_SOURCE_DIR}/t/unit-tests/${unit_test}.c")
- target_link_libraries("${unit_test}" unit-test-lib unit-test-lib-oid common-main)
+ target_link_libraries("${unit_test}" unit-test-lib common-main)
set_target_properties("${unit_test}"
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
if(MSVC)
@@ -1004,14 +1001,14 @@ foreach(unit_test ${unit_test_PROGRAMS})
endif()
endforeach()
-parse_makefile_for_scripts(unit_tests_SUITES "UNIT_TESTS_SUITES" "")
+parse_makefile_for_scripts(clar_test_SUITES "CLAR_TEST_SUITES" "")
set(clar_decls "")
set(clar_cbs "")
set(clar_cbs_count 0)
set(clar_suites "static struct clar_suite _clar_suites[] = {\n")
-list(LENGTH unit_tests_SUITES clar_suites_count)
-foreach(suite ${unit_tests_SUITES})
+list(LENGTH clar_test_SUITES clar_suites_count)
+foreach(suite ${clar_test_SUITES})
file(STRINGS "${CMAKE_SOURCE_DIR}/t/unit-tests/${suite}.c" decls
REGEX "^void test_${suite}__[a-zA-Z_0-9][a-zA-Z_0-9]*\\(void\\)$")
@@ -1042,9 +1039,9 @@ string(APPEND clar_suites
file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" "${clar_decls}")
file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" "${clar_decls}" "${clar_cbs}" "${clar_suites}")
-list(TRANSFORM unit_tests_SUITES PREPEND "${CMAKE_SOURCE_DIR}/t/unit-tests/")
-list(TRANSFORM unit_tests_SUITES APPEND ".c")
-add_library(unit-tests-lib ${unit_tests_SUITES} "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c")
+list(TRANSFORM clar_test_SUITES PREPEND "${CMAKE_SOURCE_DIR}/t/unit-tests/")
+list(TRANSFORM clar_test_SUITES APPEND ".c")
+add_library(unit-tests-lib ${clar_test_SUITES} "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c")
target_include_directories(unit-tests-lib PRIVATE "${CMAKE_SOURCE_DIR}/t/unit-tests")
add_executable(unit-tests "${CMAKE_SOURCE_DIR}/t/unit-tests/unit-test.c")
target_link_libraries(unit-tests unit-tests-lib common-main)
@@ -1062,7 +1059,7 @@ parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/")
-add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES} ${test-reftable_SOURCES})
+add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES})
target_link_libraries(test-tool test-lib common-main)
set_target_properties(test-fake-ssh test-tool
diff --git a/diff.c b/diff.c
index 3be927b073..84a6bb0868 100644
--- a/diff.c
+++ b/diff.c
@@ -3675,6 +3675,7 @@ static void builtin_diff(const char *name_a,
emit_diff_symbol(o, DIFF_SYMBOL_BINARY_FILES,
sb.buf, sb.len, 0);
strbuf_release(&sb);
+ o->found_changes = 1;
goto free_ab_and_return;
}
if (fill_mmfile(o->repo, &mf1, one) < 0 ||
diff --git a/diffcore-rename.c b/diffcore-rename.c
index fab45b10d7..3d6826baa3 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -933,7 +933,7 @@ static int find_basename_matches(struct diff_options *options,
* spend more cycles to find similarities between files, so it may
* be less likely that this heuristic is wanted. If someone is
* doing break detection, that means they do not want filename
- * similarity to imply any form of content similiarity, and thus
+ * similarity to imply any form of content similarity, and thus
* this heuristic would definitely be incompatible.
*/
@@ -1534,7 +1534,7 @@ void diffcore_rename_extended(struct diff_options *options,
* - remove ones not found in relevant_sources
* and
* - remove ones in relevant_sources which are needed only
- * for directory renames IF no ancestory directory
+ * for directory renames IF no ancestry directory
* actually needs to know any more individual path
* renames under them
*/
diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c
index e818583420..a6587a8972 100644
--- a/fsmonitor-settings.c
+++ b/fsmonitor-settings.c
@@ -7,7 +7,7 @@
#include "fsmonitor-path-utils.h"
/*
- * We keep this structure defintion private and have getters
+ * We keep this structure definition private and have getters
* for all fields so that we can lazy load it as needed.
*/
struct fsmonitor_settings {
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 994431c887..8dbe21d588 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -612,7 +612,7 @@ python_conf() {
ln -sf "$root/static" "$fqgitdir/gitweb/$httpd_only/"
# generate a standalone 'python http.server' script in $fqgitdir/gitweb
- # This asumes that python is in user's $PATH
+ # This assumes that python is in user's $PATH
# This script is Python 2 and 3 compatible
cat > "$fqgitdir/gitweb/gitweb.py" <<EOF
#!/usr/bin/env python
diff --git a/git-p4.py b/git-p4.py
index f1ab31d540..c0ca7becaf 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -54,7 +54,7 @@ import time
import zipfile
import zlib
-# On python2.7 where raw_input() and input() are both availble,
+# On python2.7 where raw_input() and input() are both available,
# we want raw_input's semantics, but aliased to input for python3
# compatibility
# support basestring in python3
@@ -1804,7 +1804,7 @@ class P4Submit(Command, P4UserMap):
status from the script will abort the process.
The purpose of the hook is to edit the message file in place, and it is not
- supressed by the `--no-verify` option. This hook is called even if
+ suppressed by the `--no-verify` option. This hook is called even if
`--prepare-p4-only` is set.
The `p4-changelist` hook is executed after the changelist message has been
diff --git a/gpg-interface.c b/gpg-interface.c
index cf6126b5aa..07335987a6 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -400,7 +400,7 @@ static void parse_ssh_output(struct signature_check *sigc)
* Note that "PRINCIPAL" can contain whitespace, "RSA" and
* "SHA256" part could be a different token that names of
* the algorithms used, and "FINGERPRINT" is a hexadecimal
- * string. By finding the last occurence of " with ", we can
+ * string. By finding the last occurrence of " with ", we can
* reliably parse out the PRINCIPAL.
*/
sigc->result = 'B';
diff --git a/http.c b/http.c
index 6c6cc5c822..376af88c5d 100644
--- a/http.c
+++ b/http.c
@@ -1707,7 +1707,7 @@ void run_active_slot(struct active_request_slot *slot)
* The value of slot->finished we set before the loop was used
* to set our "finished" variable when our request completed.
*
- * 1. The slot may not have been reused for another requst
+ * 1. The slot may not have been reused for another request
* yet, in which case it still has &finished.
*
* 2. The slot may already be in-use to serve another request,
diff --git a/merge-ll.c b/merge-ll.c
index badb6dea57..8e63071922 100644
--- a/merge-ll.c
+++ b/merge-ll.c
@@ -334,7 +334,7 @@ static int read_merge_config(const char *var, const char *value,
* %X - the revision for our version
* %Y - the revision for their version
*
- * If the file is not named indentically in all versions, then each
+ * If the file is not named identically in all versions, then each
* revision is joined with the corresponding path, separated by a colon.
* The external merge driver should write the results in the
* file named by %A, and signal that it has done with zero exit
diff --git a/merge-ort.c b/merge-ort.c
index 0ed3cd06b1..8b81153e8f 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -1147,7 +1147,7 @@ static void collect_rename_info(struct merge_options *opt,
* Update dir_rename_mask (determines ignore-rename-source validity)
*
* dir_rename_mask helps us keep track of when directory rename
- * detection may be relevant. Basically, whenver a directory is
+ * detection may be relevant. Basically, whenever a directory is
* removed on one side of history, and a file is added to that
* directory on the other side of history, directory rename
* detection is relevant (meaning we have to detect renames for all
@@ -3837,7 +3837,7 @@ static int write_completed_directory(struct merge_options *opt,
* src/moduleB 2
*
* which is used to know that xtract.c & token.txt are from the
- * toplevel dirctory, while umm.c & stuff.h & baz.c are from the
+ * toplevel directory, while umm.c & stuff.h & baz.c are from the
* src/moduleB directory. Again, following the example above,
* once we need to process src/moduleB, then info->offsets is
* updated to
diff --git a/object-file.c b/object-file.c
index 968da27cd4..7ac9533ab1 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2308,7 +2308,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
/*
* Common steps for write_loose_object and stream_loose_object to
- * end writing loose oject:
+ * end writing loose object:
*
* - End the compression of zlib stream.
* - Get the calculated oid.
diff --git a/pretty.c b/pretty.c
index 5e5ae45253..6403e26890 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2205,7 +2205,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
}
/*
- * pp_handle_indent() prints out the intendation, and
+ * pp_handle_indent() prints out the indentation, and
* the whole line (without the final newline), after
* de-tabifying.
*/
diff --git a/read-cache-ll.h b/read-cache-ll.h
index e0e39607ef..b5d11d07a8 100644
--- a/read-cache-ll.h
+++ b/read-cache-ll.h
@@ -151,7 +151,7 @@ enum sparse_index_mode {
/*
* The index has already been collapsed to sparse directories
- * whereever possible.
+ * wherever possible.
*/
INDEX_COLLAPSED,
diff --git a/rebase.c b/rebase.c
index 69a1822da3..9d1ae95978 100644
--- a/rebase.c
+++ b/rebase.c
@@ -11,7 +11,7 @@
* The callers that care if (any) rebase is requested should say
* if (REBASE_TRUE <= rebase_parse_value(string))
*
- * The callers that want to differenciate an unrecognised value and
+ * The callers that want to differentiate an unrecognised value and
* false can do so by treating _INVALID and _FALSE differently.
*/
enum rebase_type rebase_parse_value(const char *value)
diff --git a/ref-filter.c b/ref-filter.c
index fce96d7739..dd195007ce 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2385,7 +2385,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
CALLOC_ARRAY(ref->value, used_atom_cnt);
/**
- * NEEDSWORK: The following code might be unncessary if all codepaths
+ * NEEDSWORK: The following code might be unnecessary if all codepaths
* that call populate_value() populates the symref member of ref_array_item
* like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath
* that calls populate_value() without first populating symref.
diff --git a/refs.c b/refs.c
index 3bee3e7829..5f729ed412 100644
--- a/refs.c
+++ b/refs.c
@@ -1518,6 +1518,19 @@ const char **hidden_refs_to_excludes(const struct strvec *hide_refs)
return hide_refs->v;
}
+const char **get_namespaced_exclude_patterns(const char **exclude_patterns,
+ const char *namespace,
+ struct strvec *out)
+{
+ if (!namespace || !*namespace || !exclude_patterns || !*exclude_patterns)
+ return exclude_patterns;
+
+ for (size_t i = 0; exclude_patterns[i]; i++)
+ strvec_pushf(out, "%s%s", namespace, exclude_patterns[i]);
+
+ return out->v;
+}
+
const char *find_descendant_ref(const char *dirname,
const struct string_list *extras,
const struct string_list *skip)
@@ -1635,11 +1648,19 @@ int refs_for_each_namespaced_ref(struct ref_store *refs,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
{
- struct strbuf buf = STRBUF_INIT;
+ struct strvec namespaced_exclude_patterns = STRVEC_INIT;
+ struct strbuf prefix = STRBUF_INIT;
int ret;
- strbuf_addf(&buf, "%srefs/", get_git_namespace());
- ret = do_for_each_ref(refs, buf.buf, exclude_patterns, fn, 0, 0, cb_data);
- strbuf_release(&buf);
+
+ exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
+ get_git_namespace(),
+ &namespaced_exclude_patterns);
+
+ strbuf_addf(&prefix, "%srefs/", get_git_namespace());
+ ret = do_for_each_ref(refs, prefix.buf, exclude_patterns, fn, 0, 0, cb_data);
+
+ strvec_clear(&namespaced_exclude_patterns);
+ strbuf_release(&prefix);
return ret;
}
@@ -1720,6 +1741,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
{
+ struct strvec namespaced_exclude_patterns = STRVEC_INIT;
struct string_list prefixes = STRING_LIST_INIT_DUP;
struct string_list_item *prefix;
struct strbuf buf = STRBUF_INIT;
@@ -1731,6 +1753,10 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
strbuf_addstr(&buf, namespace);
namespace_len = buf.len;
+ exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
+ namespace,
+ &namespaced_exclude_patterns);
+
for_each_string_list_item(prefix, &prefixes) {
strbuf_addstr(&buf, prefix->string);
ret = refs_for_each_fullref_in(ref_store, buf.buf,
@@ -1740,6 +1766,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
strbuf_setlen(&buf, namespace_len);
}
+ strvec_clear(&namespaced_exclude_patterns);
string_list_clear(&prefixes, 0);
strbuf_release(&buf);
return ret;
diff --git a/refs.h b/refs.h
index f2c4ccde61..108dfc93b3 100644
--- a/refs.h
+++ b/refs.h
@@ -17,7 +17,7 @@ enum ref_storage_format ref_storage_format_by_name(const char *name);
const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format);
/*
- * Resolve a reference, recursively following symbolic refererences.
+ * Resolve a reference, recursively following symbolic references.
*
* Return the name of the non-symbolic reference that ultimately pointed
* at the resolved object name. The return value, if not NULL, is a
@@ -490,7 +490,7 @@ int refs_delete_reflog(struct ref_store *refs, const char *refname);
* from UTC. Its absolute value is formed by multiplying the hour
* part by 100 and adding the minute part. For example, 1 hour ahead
* of UTC, CET == "+0100", is represented as positive one hundred (not
- * postiive sixty).
+ * positive sixty).
*
* The msg parameter is a single complete line; a reflog message given
* to refs_delete_ref, refs_update_ref, etc. is returned to the
@@ -861,6 +861,15 @@ int ref_is_hidden(const char *, const char *, const struct strvec *);
*/
const char **hidden_refs_to_excludes(const struct strvec *hide_refs);
+/*
+ * Prefix all exclude patterns with the namespace, if any. This is required
+ * because exclude patterns apply to the stripped reference name, not the full
+ * reference name with the namespace.
+ */
+const char **get_namespaced_exclude_patterns(const char **exclude_patterns,
+ const char *namespace,
+ struct strvec *out);
+
/* Is this a per-worktree ref living in the refs/ namespace? */
int is_per_worktree_ref(const char *refname);
@@ -988,7 +997,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt);
/*
* Some of the names specified by refs have special meaning to Git.
- * Organize these namespaces in a comon 'ref_namespace' array for
+ * Organize these namespaces in a common 'ref_namespace' array for
* reference from multiple places in the codebase.
*/
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 043e19439f..f5f957e6de 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -22,6 +22,7 @@
#include "../repo-settings.h"
#include "../setup.h"
#include "../strmap.h"
+#include "../trace2.h"
#include "parse.h"
#include "refs-internal.h"
@@ -451,10 +452,81 @@ struct reftable_ref_iterator {
const char *prefix;
size_t prefix_len;
+ char **exclude_patterns;
+ size_t exclude_patterns_index;
+ size_t exclude_patterns_strlen;
unsigned int flags;
int err;
};
+/*
+ * Handle exclude patterns. Returns either `1`, which tells the caller that the
+ * current reference shall not be shown. Or `0`, which indicates that it should
+ * be shown.
+ */
+static int should_exclude_current_ref(struct reftable_ref_iterator *iter)
+{
+ while (iter->exclude_patterns[iter->exclude_patterns_index]) {
+ const char *pattern = iter->exclude_patterns[iter->exclude_patterns_index];
+ char *ref_after_pattern;
+ int cmp;
+
+ /*
+ * Lazily cache the pattern length so that we don't have to
+ * recompute it every time this function is called.
+ */
+ if (!iter->exclude_patterns_strlen)
+ iter->exclude_patterns_strlen = strlen(pattern);
+
+ /*
+ * When the reference name is lexicographically bigger than the
+ * current exclude pattern we know that it won't ever match any
+ * of the following references, either. We thus advance to the
+ * next pattern and re-check whether it matches.
+ *
+ * Otherwise, if it's smaller, then we do not have a match and
+ * thus want to show the current reference.
+ */
+ cmp = strncmp(iter->ref.refname, pattern,
+ iter->exclude_patterns_strlen);
+ if (cmp > 0) {
+ iter->exclude_patterns_index++;
+ iter->exclude_patterns_strlen = 0;
+ continue;
+ }
+ if (cmp < 0)
+ return 0;
+
+ /*
+ * The reference shares a prefix with the exclude pattern and
+ * shall thus be omitted. We skip all references that match the
+ * pattern by seeking to the first reference after the block of
+ * matches.
+ *
+ * This is done by appending the highest possible character to
+ * the pattern. Consequently, all references that have the
+ * pattern as prefix and whose suffix starts with anything in
+ * the range [0x00, 0xfe] are skipped. And given that 0xff is a
+ * non-printable character that shouldn't ever be in a ref name,
+ * we'd not yield any such record, either.
+ *
+ * Note that the seeked-to reference may also be excluded. This
+ * is not handled here though, but the caller is expected to
+ * loop and re-verify the next reference for us.
+ */
+ ref_after_pattern = xstrfmt("%s%c", pattern, 0xff);
+ iter->err = reftable_iterator_seek_ref(&iter->iter, ref_after_pattern);
+ iter->exclude_patterns_index++;
+ iter->exclude_patterns_strlen = 0;
+ trace2_counter_add(TRACE2_COUNTER_ID_REFTABLE_RESEEKS, 1);
+
+ free(ref_after_pattern);
+ return 1;
+ }
+
+ return 0;
+}
+
static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
{
struct reftable_ref_iterator *iter =
@@ -485,6 +557,9 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
break;
}
+ if (iter->exclude_patterns && should_exclude_current_ref(iter))
+ continue;
+
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) !=
REF_WORKTREE_CURRENT)
@@ -574,6 +649,11 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
(struct reftable_ref_iterator *)ref_iterator;
reftable_ref_record_release(&iter->ref);
reftable_iterator_destroy(&iter->iter);
+ if (iter->exclude_patterns) {
+ for (size_t i = 0; iter->exclude_patterns[i]; i++)
+ free(iter->exclude_patterns[i]);
+ free(iter->exclude_patterns);
+ }
free(iter);
return ITER_DONE;
}
@@ -584,9 +664,53 @@ static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
.abort = reftable_ref_iterator_abort
};
+static int qsort_strcmp(const void *va, const void *vb)
+{
+ const char *a = *(const char **)va;
+ const char *b = *(const char **)vb;
+ return strcmp(a, b);
+}
+
+static char **filter_exclude_patterns(const char **exclude_patterns)
+{
+ size_t filtered_size = 0, filtered_alloc = 0;
+ char **filtered = NULL;
+
+ if (!exclude_patterns)
+ return NULL;
+
+ for (size_t i = 0; ; i++) {
+ const char *exclude_pattern = exclude_patterns[i];
+ int has_glob = 0;
+
+ if (!exclude_pattern)
+ break;
+
+ for (const char *p = exclude_pattern; *p; p++) {
+ has_glob = is_glob_special(*p);
+ if (has_glob)
+ break;
+ }
+ if (has_glob)
+ continue;
+
+ ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc);
+ filtered[filtered_size++] = xstrdup(exclude_pattern);
+ }
+
+ if (filtered_size) {
+ QSORT(filtered, filtered_size, qsort_strcmp);
+ ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc);
+ filtered[filtered_size++] = NULL;
+ }
+
+ return filtered;
+}
+
static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_store *refs,
struct reftable_stack *stack,
const char *prefix,
+ const char **exclude_patterns,
int flags)
{
struct reftable_ref_iterator *iter;
@@ -599,6 +723,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
iter->base.oid = &iter->oid;
iter->flags = flags;
iter->refs = refs;
+ iter->exclude_patterns = filter_exclude_patterns(exclude_patterns);
ret = refs->err;
if (ret)
@@ -620,7 +745,7 @@ done:
static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_store,
const char *prefix,
- const char **exclude_patterns UNUSED,
+ const char **exclude_patterns,
unsigned int flags)
{
struct reftable_ref_iterator *main_iter, *worktree_iter;
@@ -631,7 +756,8 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
required_flags |= REF_STORE_ODB;
refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin");
- main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix, flags);
+ main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix,
+ exclude_patterns, flags);
/*
* The worktree stack is only set when we're in an actual worktree
@@ -645,7 +771,8 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
* Otherwise we merge both the common and the per-worktree refs into a
* single iterator.
*/
- worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix, flags);
+ worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix,
+ exclude_patterns, flags);
return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
ref_iterator_select, NULL);
}
diff --git a/reftable/reader.c b/reftable/reader.c
index f877099087..6494ce2e32 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -328,6 +328,7 @@ static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ)
ti->typ = block_reader_type(&ti->br);
ti->block_off = off;
block_iter_seek_start(&ti->bi, &ti->br);
+ ti->is_finished = 0;
return 0;
}
diff --git a/revision.h b/revision.h
index 0e470d1df1..71e984c452 100644
--- a/revision.h
+++ b/revision.h
@@ -549,7 +549,7 @@ int rewrite_parents(struct rev_info *revs,
* The log machinery saves the original parent list so that
* get_saved_parents() can later tell what the real parents of the
* commits are, when commit->parents has been modified by history
- * simpification.
+ * simplification.
*
* get_saved_parents() will transparently return commit->parents if
* history simplification is off.
diff --git a/run-command.h b/run-command.h
index 03e7222d8b..0df25e445f 100644
--- a/run-command.h
+++ b/run-command.h
@@ -535,7 +535,7 @@ enum start_bg_result {
/* timeout expired waiting for child to become "ready" */
SBGR_TIMEOUT,
- /* child process exited or was signalled before becomming "ready" */
+ /* child process exited or was signalled before becoming "ready" */
SBGR_DIED,
};
diff --git a/setup.c b/setup.c
index 7499191472..94e79b2e48 100644
--- a/setup.c
+++ b/setup.c
@@ -524,7 +524,7 @@ static void setup_original_cwd(void)
* directory we inherited from our parent process, which is a
* directory we want to avoid removing.
*
- * For convience, we would like to have the path relative to the
+ * For convenience, we would like to have the path relative to the
* worktree instead of an absolute path.
*
* Yes, startup_info->original_cwd is usually the same as 'prefix',
diff --git a/sideband.c b/sideband.c
index 4e816be4e9..02805573fa 100644
--- a/sideband.c
+++ b/sideband.c
@@ -191,7 +191,7 @@ int demultiplex_sideband(const char *me, int status,
int linelen = brk - b;
/*
- * For message accross packet boundary, there would have
+ * For message across packet boundary, there would have
* a nonempty "scratch" buffer from last call of this
* function, and there may have a leading CR/LF in "buf".
* For this case we should add a clear-to-eol suffix to
diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh
index 1359574419..3256e4462f 100755
--- a/t/t1419-exclude-refs.sh
+++ b/t/t1419-exclude-refs.sh
@@ -8,12 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-if test_have_prereq !REFFILES
-then
- skip_all='skipping `git for-each-ref --exclude` tests; need files backend'
- test_done
-fi
-
for_each_ref__exclude () {
GIT_TRACE2_PERF=1 test-tool ref-store main \
for-each-ref--exclude "$@" >actual.raw
@@ -28,7 +22,14 @@ assert_jumps () {
local nr="$1"
local trace="$2"
- grep -q "name:jumps_made value:$nr$" $trace
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ grep -q "name:jumps_made value:$nr$" $trace;;
+ reftable)
+ grep -q "name:reseeks_made value:$nr$" $trace;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
}
assert_no_jumps () {
@@ -89,7 +90,14 @@ test_expect_success 'adjacent, non-overlapping excluded regions' '
for_each_ref refs/heads/foo refs/heads/quux >expect &&
test_cmp expect actual &&
- assert_jumps 1 perf
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 2 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
'
test_expect_success 'overlapping excluded regions' '
@@ -106,7 +114,30 @@ test_expect_success 'several overlapping excluded regions' '
for_each_ref refs/heads/quux >expect &&
test_cmp expect actual &&
- assert_jumps 1 perf
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 3 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
+'
+
+test_expect_success 'unordered excludes' '
+ for_each_ref__exclude refs/heads \
+ refs/heads/foo refs/heads/baz >actual 2>perf &&
+ for_each_ref refs/heads/bar refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 2 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
'
test_expect_success 'non-matching excluded section' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 94671d3c46..4d9744e5fc 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -5,6 +5,7 @@
test_description='tests to ensure compatibility between am and interactive backends'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index d644310e22..1cea73ef5a 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -145,6 +145,14 @@ test_expect_success 'option errors are not confused by --exit-code' '
for option in --exit-code --quiet
do
+ test_expect_success "git diff $option returns 1 for changed binary file" "
+ test_when_finished 'rm -f .gitattributes' &&
+ git reset --hard &&
+ echo a binary >.gitattributes &&
+ echo 2 >>a &&
+ test_expect_code 1 git diff $option
+ "
+
test_expect_success "git diff $option returns 1 for copied file" "
git reset --hard &&
cp a copy &&
diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh
index ac72eeaf27..5e6e203aa5 100755
--- a/t/t4107-apply-ignore-whitespace.sh
+++ b/t/t4107-apply-ignore-whitespace.sh
@@ -3,9 +3,9 @@
# Copyright (c) 2009 Giuseppe Bilotta
#
-test_description='git-apply --ignore-whitespace.
+test_description='git-apply --ignore-whitespace.'
-'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This primes main.c file that indents without using HT at all.
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 485c7d2d12..cdffee0273 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -2,6 +2,7 @@
test_description='core.whitespace rules and git apply'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
prepare_test_file () {
diff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh
index 090987c89b..f248cc2a00 100755
--- a/t/t4125-apply-ws-fuzz.sh
+++ b/t/t4125-apply-ws-fuzz.sh
@@ -2,6 +2,7 @@
test_description='applying patch that has broken whitespaces in context'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh
index 8bbf8260fa..7981931b4e 100755
--- a/t/t4138-apply-ws-expansion.sh
+++ b/t/t4138-apply-ws-expansion.sh
@@ -5,6 +5,7 @@
test_description='git apply test patches with whitespace expansion.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh
index 05090feaf9..f029ae0d28 100755
--- a/t/t5509-fetch-push-namespaces.sh
+++ b/t/t5509-fetch-push-namespaces.sh
@@ -96,6 +96,7 @@ test_expect_success 'hide namespaced refs with transfer.hideRefs' '
'
test_expect_success 'check that transfer.hideRefs does not match unstripped refs' '
+ git -C pushee pack-refs --all &&
GIT_NAMESPACE=namespace \
git -C pushee -c transfer.hideRefs=refs/namespaces/namespace/refs/tags \
ls-remote "ext::git %s ." >actual &&
@@ -123,6 +124,14 @@ test_expect_success 'try to update a ref that is not hidden' '
git -C original push pushee-namespaced main
'
+test_expect_success 'git-receive-pack(1) with transfer.hideRefs does not match unstripped refs during advertisement' '
+ git -C pushee update-ref refs/namespaces/namespace/refs/heads/foo/1 refs/namespaces/namespace/refs/heads/main &&
+ git -C pushee pack-refs --all &&
+ test_config -C pushee transfer.hideRefs refs/namespaces/namespace/refs/heads/foo &&
+ GIT_TRACE_PACKET="$(pwd)/trace" git -C original push pushee-namespaced main &&
+ test_grep refs/heads/foo/1 trace
+'
+
test_expect_success 'try to update a hidden full ref' '
test_config -C pushee transfer.hideRefs "^refs/namespaces/namespace/refs/heads/main" &&
test_must_fail git -C original push pushee-namespaced main
diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c
new file mode 100644
index 0000000000..ab1fa44a28
--- /dev/null
+++ b/t/unit-tests/lib-reftable.c
@@ -0,0 +1,93 @@
+#include "lib-reftable.h"
+#include "test-lib.h"
+#include "reftable/constants.h"
+#include "reftable/writer.h"
+
+void t_reftable_set_hash(uint8_t *p, int i, uint32_t id)
+{
+ memset(p, (uint8_t)i, hash_size(id));
+}
+
+static ssize_t strbuf_writer_write(void *b, const void *data, size_t sz)
+{
+ strbuf_add(b, data, sz);
+ return sz;
+}
+
+static int strbuf_writer_flush(void *arg UNUSED)
+{
+ return 0;
+}
+
+struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,
+ struct reftable_write_options *opts)
+{
+ return reftable_new_writer(&strbuf_writer_write,
+ &strbuf_writer_flush,
+ buf, opts);
+}
+
+void t_reftable_write_to_buf(struct strbuf *buf,
+ struct reftable_ref_record *refs,
+ size_t nrefs,
+ struct reftable_log_record *logs,
+ size_t nlogs,
+ struct reftable_write_options *_opts)
+{
+ struct reftable_write_options opts = { 0 };
+ const struct reftable_stats *stats;
+ struct reftable_writer *writer;
+ uint64_t min = 0xffffffff;
+ uint64_t max = 0;
+ int ret;
+
+ if (_opts)
+ opts = *_opts;
+
+ for (size_t i = 0; i < nrefs; i++) {
+ uint64_t ui = refs[i].update_index;
+ if (ui > max)
+ max = ui;
+ if (ui < min)
+ min = ui;
+ }
+ for (size_t i = 0; i < nlogs; i++) {
+ uint64_t ui = logs[i].update_index;
+ if (ui > max)
+ max = ui;
+ if (ui < min)
+ min = ui;
+ }
+
+ writer = t_reftable_strbuf_writer(buf, &opts);
+ reftable_writer_set_limits(writer, min, max);
+
+ if (nrefs) {
+ ret = reftable_writer_add_refs(writer, refs, nrefs);
+ check_int(ret, ==, 0);
+ }
+
+ if (nlogs) {
+ ret = reftable_writer_add_logs(writer, logs, nlogs);
+ check_int(ret, ==, 0);
+ }
+
+ ret = reftable_writer_close(writer);
+ check_int(ret, ==, 0);
+
+ stats = reftable_writer_stats(writer);
+ for (size_t i = 0; i < stats->ref_stats.blocks; i++) {
+ size_t off = i * (opts.block_size ? opts.block_size
+ : DEFAULT_BLOCK_SIZE);
+ if (!off)
+ off = header_size(opts.hash_id == GIT_SHA256_FORMAT_ID ? 2 : 1);
+ check_char(buf->buf[off], ==, 'r');
+ }
+
+ if (nrefs)
+ check_int(stats->ref_stats.blocks, >, 0);
+ if (nlogs)
+ check_int(stats->log_stats.blocks, >, 0);
+
+ reftable_writer_free(writer);
+}
diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h
new file mode 100644
index 0000000000..d115419084
--- /dev/null
+++ b/t/unit-tests/lib-reftable.h
@@ -0,0 +1,20 @@
+#ifndef LIB_REFTABLE_H
+#define LIB_REFTABLE_H
+
+#include "git-compat-util.h"
+#include "strbuf.h"
+#include "reftable/reftable-writer.h"
+
+void t_reftable_set_hash(uint8_t *p, int i, uint32_t id);
+
+struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,
+ struct reftable_write_options *opts);
+
+void t_reftable_write_to_buf(struct strbuf *buf,
+ struct reftable_ref_record *refs,
+ size_t nrecords,
+ struct reftable_log_record *logs,
+ size_t nlogs,
+ struct reftable_write_options *opts);
+
+#endif
diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c
index e9d100a01e..19e54bdfb8 100644
--- a/t/unit-tests/t-reftable-merged.c
+++ b/t/unit-tests/t-reftable-merged.c
@@ -7,6 +7,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "test-lib.h"
+#include "lib-reftable.h"
#include "reftable/blocksource.h"
#include "reftable/constants.h"
#include "reftable/merged.h"
@@ -15,77 +16,6 @@ https://developers.google.com/open-source/licenses/bsd
#include "reftable/reftable-merged.h"
#include "reftable/reftable-writer.h"
-static ssize_t strbuf_add_void(void *b, const void *data, const size_t sz)
-{
- strbuf_add(b, data, sz);
- return sz;
-}
-
-static int noop_flush(void *arg UNUSED)
-{
- return 0;
-}
-
-static void write_test_table(struct strbuf *buf,
- struct reftable_ref_record refs[], const size_t n)
-{
- uint64_t min = 0xffffffff;
- uint64_t max = 0;
- size_t i;
- int err;
-
- struct reftable_write_options opts = {
- .block_size = 256,
- };
- struct reftable_writer *w = NULL;
- for (i = 0; i < n; i++) {
- uint64_t ui = refs[i].update_index;
- if (ui > max)
- max = ui;
- if (ui < min)
- min = ui;
- }
-
- w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- reftable_writer_set_limits(w, min, max);
-
- for (i = 0; i < n; i++) {
- uint64_t before = refs[i].update_index;
- int n = reftable_writer_add_ref(w, &refs[i]);
- check_int(n, ==, 0);
- check_int(before, ==, refs[i].update_index);
- }
-
- err = reftable_writer_close(w);
- check(!err);
-
- reftable_writer_free(w);
-}
-
-static void write_test_log_table(struct strbuf *buf, struct reftable_log_record logs[],
- const size_t n, const uint64_t update_index)
-{
- int err;
-
- struct reftable_write_options opts = {
- .block_size = 256,
- .exact_log_message = 1,
- };
- struct reftable_writer *w = NULL;
- w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- reftable_writer_set_limits(w, update_index, update_index);
-
- for (size_t i = 0; i < n; i++) {
- int err = reftable_writer_add_log(w, &logs[i]);
- check(!err);
- }
-
- err = reftable_writer_close(w);
- check(!err);
-
- reftable_writer_free(w);
-}
-
static struct reftable_merged_table *
merged_table_from_records(struct reftable_ref_record **refs,
struct reftable_block_source **source,
@@ -93,13 +23,16 @@ merged_table_from_records(struct reftable_ref_record **refs,
struct strbuf *buf, const size_t n)
{
struct reftable_merged_table *mt = NULL;
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
REFTABLE_CALLOC_ARRAY(*source, n);
for (size_t i = 0; i < n; i++) {
- write_test_table(&buf[i], refs[i], sizes[i]);
+ t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);
block_source_from_strbuf(&(*source)[i], &buf[i]);
err = reftable_reader_new(&(*readers)[i], &(*source)[i],
@@ -261,6 +194,81 @@ static void t_merged_refs(void)
reftable_free(bs);
}
+static void t_merged_seek_multiple_times(void)
+{
+ struct reftable_ref_record r1[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ },
+ {
+ .refname = (char *) "c",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 2 },
+ }
+ };
+ struct reftable_ref_record r2[] = {
+ {
+ .refname = (char *) "b",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 3 },
+ },
+ {
+ .refname = (char *) "d",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 4 },
+ },
+ };
+ struct reftable_ref_record *refs[] = {
+ r1, r2,
+ };
+ size_t sizes[] = {
+ ARRAY_SIZE(r1), ARRAY_SIZE(r2),
+ };
+ struct strbuf bufs[] = {
+ STRBUF_INIT, STRBUF_INIT,
+ };
+ struct reftable_block_source *sources = NULL;
+ struct reftable_reader **readers = NULL;
+ struct reftable_ref_record rec = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_merged_table *mt;
+
+ mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2);
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+
+ for (size_t i = 0; i < 5; i++) {
+ int err = reftable_iterator_seek_ref(&it, "c");
+ check(!err);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(!err);
+ err = reftable_ref_record_equal(&rec, &r1[1], GIT_SHA1_RAWSZ);
+ check(err == 1);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(!err);
+ err = reftable_ref_record_equal(&rec, &r2[1], GIT_SHA1_RAWSZ);
+ check(err == 1);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(err > 0);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(bufs); i++)
+ strbuf_release(&bufs[i]);
+ readers_destroy(readers, ARRAY_SIZE(refs));
+ reftable_ref_record_release(&rec);
+ reftable_iterator_destroy(&it);
+ reftable_merged_table_free(mt);
+ reftable_free(sources);
+}
+
static struct reftable_merged_table *
merged_table_from_log_records(struct reftable_log_record **logs,
struct reftable_block_source **source,
@@ -268,13 +276,17 @@ merged_table_from_log_records(struct reftable_log_record **logs,
struct strbuf *buf, const size_t n)
{
struct reftable_merged_table *mt = NULL;
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ .exact_log_message = 1,
+ };
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
REFTABLE_CALLOC_ARRAY(*source, n);
for (size_t i = 0; i < n; i++) {
- write_test_log_table(&buf[i], logs[i], sizes[i], i + 1);
+ t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);
block_source_from_strbuf(&(*source)[i], &buf[i]);
err = reftable_reader_new(&(*readers)[i], &(*source)[i],
@@ -402,9 +414,7 @@ static void t_default_write_opts(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
-
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record rec = {
.refname = (char *) "master",
.update_index = 1,
@@ -448,6 +458,7 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
TEST(t_default_write_opts(), "merged table with default write opts");
TEST(t_merged_logs(), "merged table with multiple log updates for same ref");
TEST(t_merged_refs(), "merged table with multiple updates to same ref");
+ TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times");
TEST(t_merged_single_record(), "ref ocurring in only one record can be fetched");
return test_done();
diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c
new file mode 100644
index 0000000000..eea86966c0
--- /dev/null
+++ b/t/unit-tests/t-reftable-reader.c
@@ -0,0 +1,96 @@
+#include "test-lib.h"
+#include "lib-reftable.h"
+#include "reftable/blocksource.h"
+#include "reftable/reader.h"
+
+static int t_reader_seek_once(void)
+{
+ struct reftable_ref_record records[] = {
+ {
+ .refname = (char *) "refs/heads/main",
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 42 },
+ },
+ };
+ struct reftable_block_source source = { 0 };
+ struct reftable_ref_record ref = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader *reader;
+ struct strbuf buf = STRBUF_INIT;
+ int ret;
+
+ t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ block_source_from_strbuf(&source, &buf);
+
+ ret = reftable_reader_new(&reader, &source, "name");
+ check(!ret);
+
+ reftable_reader_init_ref_iterator(reader, &it);
+ ret = reftable_iterator_seek_ref(&it, "");
+ check(!ret);
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check(!ret);
+
+ ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ);
+ check_int(ret, ==, 1);
+
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check_int(ret, ==, 1);
+
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ reftable_reader_decref(reader);
+ strbuf_release(&buf);
+ return 0;
+}
+
+static int t_reader_reseek(void)
+{
+ struct reftable_ref_record records[] = {
+ {
+ .refname = (char *) "refs/heads/main",
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 42 },
+ },
+ };
+ struct reftable_block_source source = { 0 };
+ struct reftable_ref_record ref = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader *reader;
+ struct strbuf buf = STRBUF_INIT;
+ int ret;
+
+ t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ block_source_from_strbuf(&source, &buf);
+
+ ret = reftable_reader_new(&reader, &source, "name");
+ check(!ret);
+
+ reftable_reader_init_ref_iterator(reader, &it);
+
+ for (size_t i = 0; i < 5; i++) {
+ ret = reftable_iterator_seek_ref(&it, "");
+ check(!ret);
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check(!ret);
+
+ ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ);
+ check_int(ret, ==, 1);
+
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check_int(ret, ==, 1);
+ }
+
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ reftable_reader_decref(reader);
+ strbuf_release(&buf);
+ return 0;
+}
+
+int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
+{
+ TEST(t_reader_seek_once(), "reader can seek once");
+ TEST(t_reader_reseek(), "reader can reseek multiple times");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c
index 82bfaf3287..e1b235a5f1 100644
--- a/t/unit-tests/t-reftable-readwrite.c
+++ b/t/unit-tests/t-reftable-readwrite.c
@@ -7,6 +7,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "test-lib.h"
+#include "lib-reftable.h"
#include "reftable/basics.h"
#include "reftable/blocksource.h"
#include "reftable/reader.h"
@@ -15,22 +16,6 @@ https://developers.google.com/open-source/licenses/bsd
static const int update_index = 5;
-static void set_test_hash(uint8_t *p, int i)
-{
- memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
-}
-
-static ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
-{
- strbuf_add(b, data, sz);
- return sz;
-}
-
-static int noop_flush(void *arg UNUSED)
-{
- return 0;
-}
-
static void t_buffer(void)
{
struct strbuf buf = STRBUF_INIT;
@@ -62,61 +47,34 @@ static void write_table(char ***names, struct strbuf *buf, int N,
.block_size = block_size,
.hash_id = hash_id,
};
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- struct reftable_ref_record ref = { 0 };
- int i = 0, n;
- struct reftable_log_record log = { 0 };
- const struct reftable_stats *stats = NULL;
+ struct reftable_ref_record *refs;
+ struct reftable_log_record *logs;
+ int i;
REFTABLE_CALLOC_ARRAY(*names, N + 1);
+ REFTABLE_CALLOC_ARRAY(refs, N);
+ REFTABLE_CALLOC_ARRAY(logs, N);
- reftable_writer_set_limits(w, update_index, update_index);
for (i = 0; i < N; i++) {
- char name[100];
- int n;
-
- snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
-
- ref.refname = name;
- ref.update_index = update_index;
- ref.value_type = REFTABLE_REF_VAL1;
- set_test_hash(ref.value.val1, i);
- (*names)[i] = xstrdup(name);
-
- n = reftable_writer_add_ref(w, &ref);
- check_int(n, ==, 0);
+ refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i);
+ refs[i].update_index = update_index;
+ refs[i].value_type = REFTABLE_REF_VAL1;
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
}
for (i = 0; i < N; i++) {
- char name[100];
- int n;
-
- snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
-
- log.refname = name;
- log.update_index = update_index;
- log.value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(log.value.update.new_hash, i);
- log.value.update.message = (char *) "message";
-
- n = reftable_writer_add_log(w, &log);
- check_int(n, ==, 0);
+ logs[i].refname = (*names)[i];
+ logs[i].update_index = update_index;
+ logs[i].value_type = REFTABLE_LOG_UPDATE;
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
+ logs[i].value.update.message = (char *) "message";
}
- n = reftable_writer_close(w);
- check_int(n, ==, 0);
-
- stats = reftable_writer_stats(w);
- for (i = 0; i < stats->ref_stats.blocks; i++) {
- int off = i * opts.block_size;
- if (!off)
- off = header_size((hash_id == GIT_SHA256_FORMAT_ID) ? 2 : 1);
- check_char(buf->buf[off], ==, 'r');
- }
+ t_reftable_write_to_buf(buf, refs, N, logs, N, &opts);
- check_int(stats->log_stats.blocks, >, 0);
- reftable_writer_free(w);
+ free(refs);
+ free(logs);
}
static void t_log_buffer_size(void)
@@ -138,8 +96,7 @@ static void t_log_buffer_size(void)
.time = 0x5e430672,
.message = (char *) "commit: 9\n",
} } };
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
/* This tests buffer extension for log compression. Must use a random
hash, to ensure that the compressed part is larger than the original.
@@ -181,8 +138,7 @@ static void t_log_overflow(void)
},
},
};
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
memset(msg, 'x', sizeof(msg) - 1);
reftable_writer_set_limits(w, update_index, update_index);
@@ -208,8 +164,7 @@ static void t_log_write_read(void)
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
reftable_writer_set_limits(w, 0, N);
for (i = 0; i < N; i++) {
@@ -229,8 +184,10 @@ static void t_log_write_read(void)
log.refname = names[i];
log.update_index = i;
log.value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(log.value.update.old_hash, i);
- set_test_hash(log.value.update.new_hash, i + 1);
+ t_reftable_set_hash(log.value.update.old_hash, i,
+ GIT_SHA1_FORMAT_ID);
+ t_reftable_set_hash(log.value.update.new_hash, i + 1,
+ GIT_SHA1_FORMAT_ID);
err = reftable_writer_add_log(w, &log);
check(!err);
@@ -297,8 +254,7 @@ static void t_log_zlib_corruption(void)
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
char message[100] = { 0 };
int err, i, n;
@@ -528,15 +484,12 @@ static void t_table_refs_for(int indexed)
int err;
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
-
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
-
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_iterator it = { 0 };
int j;
- set_test_hash(want_hash, 4);
+ t_reftable_set_hash(want_hash, 4, GIT_SHA1_FORMAT_ID);
for (i = 0; i < N; i++) {
uint8_t hash[GIT_SHA1_RAWSZ];
@@ -552,8 +505,10 @@ static void t_table_refs_for(int indexed)
ref.refname = name;
ref.value_type = REFTABLE_REF_VAL2;
- set_test_hash(ref.value.val2.value, i / 4);
- set_test_hash(ref.value.val2.target_value, 3 + i / 4);
+ t_reftable_set_hash(ref.value.val2.value, i / 4,
+ GIT_SHA1_FORMAT_ID);
+ t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4,
+ GIT_SHA1_FORMAT_ID);
/* 80 bytes / entry, so 3 entries per block. Yields 17
*/
@@ -618,8 +573,7 @@ static void t_write_empty_table(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_block_source source = { 0 };
struct reftable_reader *rd = NULL;
struct reftable_ref_record rec = { 0 };
@@ -657,8 +611,7 @@ static void t_write_object_id_min_length(void)
.block_size = 75,
};
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
@@ -692,8 +645,7 @@ static void t_write_object_id_length(void)
.block_size = 75,
};
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
@@ -726,8 +678,7 @@ static void t_write_empty_key(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.refname = (char *) "",
.update_index = 1,
@@ -749,8 +700,7 @@ static void t_write_key_order(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record refs[2] = {
{
.refname = (char *) "b",
@@ -798,7 +748,7 @@ static void t_write_multiple_indices(void)
struct reftable_reader *reader;
int err, i;
- writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ writer = t_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (i = 0; i < 100; i++) {
struct reftable_ref_record ref = {
@@ -876,7 +826,7 @@ static void t_write_multi_level_index(void)
struct reftable_reader *reader;
int err;
- writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ writer = t_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (size_t i = 0; i < 200; i++) {
struct reftable_ref_record ref = {
diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c
index d62a9c1bed..65e513d5ec 100644
--- a/t/unit-tests/t-reftable-stack.c
+++ b/t/unit-tests/t-reftable-stack.c
@@ -7,17 +7,13 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "test-lib.h"
+#include "lib-reftable.h"
#include "reftable/merged.h"
#include "reftable/reader.h"
#include "reftable/reftable-error.h"
#include "reftable/stack.h"
#include <dirent.h>
-static void set_test_hash(uint8_t *p, int i)
-{
- memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
-}
-
static void clear_dir(const char *dirname)
{
struct strbuf path = STRBUF_INIT;
@@ -125,7 +121,7 @@ static void write_n_ref_tables(struct reftable_stack *st,
strbuf_reset(&buf);
strbuf_addf(&buf, "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i);
ref.refname = buf.buf;
- set_test_hash(ref.value.val1, i);
+ t_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID);
err = reftable_stack_add(st, &write_test_ref, &ref);
check(!err);
@@ -470,13 +466,13 @@ static void t_reftable_stack_add(void)
refs[i].refname = xstrdup(buf);
refs[i].update_index = i + 1;
refs[i].value_type = REFTABLE_REF_VAL1;
- set_test_hash(refs[i].value.val1, i);
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
logs[i].refname = xstrdup(buf);
logs[i].update_index = N + i + 1;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.email = xstrdup("identity@invalid");
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID);
}
for (i = 0; i < N; i++) {
@@ -562,14 +558,14 @@ static void t_reftable_stack_iterator(void)
refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
refs[i].update_index = i + 1;
refs[i].value_type = REFTABLE_REF_VAL1;
- set_test_hash(refs[i].value.val1, i);
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
logs[i].update_index = i + 1;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.email = xstrdup("johndoe@invalid");
logs[i].value.update.message = xstrdup("commit\n");
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID);
}
for (i = 0; i < N; i++) {
@@ -704,7 +700,8 @@ static void t_reftable_stack_tombstone(void)
refs[i].update_index = i + 1;
if (i % 2 == 0) {
refs[i].value_type = REFTABLE_REF_VAL1;
- set_test_hash(refs[i].value.val1, i);
+ t_reftable_set_hash(refs[i].value.val1, i,
+ GIT_SHA1_FORMAT_ID);
}
logs[i].refname = xstrdup(buf);
@@ -712,7 +709,8 @@ static void t_reftable_stack_tombstone(void)
logs[i].update_index = 42;
if (i % 2 == 0) {
logs[i].value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
logs[i].value.update.email =
xstrdup("identity@invalid");
}
@@ -844,7 +842,8 @@ static void t_reflog_expire(void)
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.time = i;
logs[i].value.update.email = xstrdup("identity@invalid");
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
}
for (i = 1; i <= N; i++) {
diff --git a/trace2.h b/trace2.h
index 19e04bf040..901f39253a 100644
--- a/trace2.h
+++ b/trace2.h
@@ -554,6 +554,7 @@ enum trace2_counter_id {
TRACE2_COUNTER_ID_TEST2, /* emits summary and thread events */
TRACE2_COUNTER_ID_PACKED_REFS_JUMPS, /* counts number of jumps */
+ TRACE2_COUNTER_ID_REFTABLE_RESEEKS, /* counts number of re-seeks */
/* counts number of fsyncs */
TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY,
diff --git a/trace2/tr2_ctr.c b/trace2/tr2_ctr.c
index d3a33715c1..036b643578 100644
--- a/trace2/tr2_ctr.c
+++ b/trace2/tr2_ctr.c
@@ -31,6 +31,11 @@ static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTER
.name = "jumps_made",
.want_per_thread_events = 0,
},
+ [TRACE2_COUNTER_ID_REFTABLE_RESEEKS] = {
+ .category = "reftable",
+ .name = "reseeks_made",
+ .want_per_thread_events = 0,
+ },
[TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY] = {
.category = "fsync",
.name = "writeout-only",
diff --git a/upload-pack.c b/upload-pack.c
index c84c3c3b1f..6d6e0f9f98 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1812,7 +1812,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)
} else {
/*
* Request had 'want's but no 'have's so we can
- * immedietly go to construct and send a pack.
+ * immediately go to construct and send a pack.
*/
state = FETCH_SEND_PACK;
}