Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
ebc5da3208 | |||
2e931843ad | |||
588de86f06 | |||
5a3db94539 | |||
5c18fde0d9 | |||
64630d807a | |||
9092a9696b | |||
d22acacf81 | |||
8c2cfa5544 | |||
8693e1cc2f | |||
cbf4e024ad | |||
f35392b018 | |||
3fea9ebdff | |||
c2f7b1026e | |||
45067fc973 | |||
782735203c | |||
80b47854ca | |||
958b2eb26c | |||
60a5f5fc79 | |||
aa4b78d483 | |||
06ca0f45a0 | |||
4baf839fe0 | |||
7b1732c116 | |||
526d56e072 | |||
95104c7e25 | |||
9393ae79c9 | |||
97c1364be6 | |||
218aa3a616 | |||
8597ea3afe | |||
c1b3c71f4b | |||
80cdaba569 | |||
bc6b8fc130 | |||
b66103c3ba | |||
ba41c1c93f | |||
a97934d820 | |||
152ff1cceb | |||
66c2827ea4 | |||
0fb370da9c | |||
d74a4e57d2 | |||
b000c59b0c | |||
10322a0aaf | |||
969eba6341 | |||
c335d74d34 | |||
e6dfcd6767 | |||
3ffefb54c0 | |||
d078d85bc3 | |||
3198b89fb2 | |||
64d3dc9468 | |||
e61a6c1d82 |
32
Documentation/RelNotes/2.0.2.txt
Normal file
32
Documentation/RelNotes/2.0.2.txt
Normal file
@ -0,0 +1,32 @@
|
||||
Git v2.0.2 Release Notes
|
||||
========================
|
||||
|
||||
* Documentation for "git submodule sync" forgot to say that the subcommand
|
||||
can take the "--recursive" option.
|
||||
|
||||
* Mishandling of patterns in .gitignore that has trailing SPs quoted
|
||||
with backslashes (e.g. ones that end with "\ ") have been
|
||||
corrected.
|
||||
|
||||
* Recent updates to "git repack" started to duplicate objects that
|
||||
are in packfiles marked with .keep flag into the new packfile by
|
||||
mistake.
|
||||
|
||||
* "git clone -b brefs/tags/bar" would have mistakenly thought we were
|
||||
following a single tag, even though it was a name of the branch,
|
||||
because it incorrectly used strstr().
|
||||
|
||||
* "%G" (nothing after G) is an invalid pretty format specifier, but
|
||||
the parser did not notice it as garbage.
|
||||
|
||||
* Code to avoid adding the same alternate object store twice was
|
||||
subtly broken for a long time, but nobody seems to have noticed.
|
||||
|
||||
* A handful of code paths had to read the commit object more than
|
||||
once when showing header fields that are usually not parsed. The
|
||||
internal data structure to keep track of the contents of the commit
|
||||
object has been updated to reduce the need for this double-reading,
|
||||
and to allow the caller find the length of the object.
|
||||
|
||||
* During "git rebase --merge", a conflicted patch could not be
|
||||
skipped with "--skip" if the next one also conflicted.
|
@ -20,7 +20,7 @@ SYNOPSIS
|
||||
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
|
||||
[commit] [--] [<path>...]
|
||||
'git submodule' [--quiet] foreach [--recursive] <command>
|
||||
'git submodule' [--quiet] sync [--] [<path>...]
|
||||
'git submodule' [--quiet] sync [--recursive] [--] [<path>...]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -43,9 +43,10 @@ unreleased) version of Git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v2.0.1/git.html[documentation for release 2.0.1]
|
||||
* link:v2.0.2/git.html[documentation for release 2.0.2]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.0.2.txt[2.0.2],
|
||||
link:RelNotes/2.0.1.txt[2.0.1],
|
||||
link:RelNotes/2.0.0.txt[2.0.0].
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v2.0.1
|
||||
DEF_VER=v2.0.2
|
||||
|
||||
LF='
|
||||
'
|
||||
|
23
alloc.c
23
alloc.c
@ -47,23 +47,32 @@ union any_object {
|
||||
|
||||
DEFINE_ALLOCATOR(blob, struct blob)
|
||||
DEFINE_ALLOCATOR(tree, struct tree)
|
||||
DEFINE_ALLOCATOR(commit, struct commit)
|
||||
DEFINE_ALLOCATOR(raw_commit, struct commit)
|
||||
DEFINE_ALLOCATOR(tag, struct tag)
|
||||
DEFINE_ALLOCATOR(object, union any_object)
|
||||
|
||||
void *alloc_commit_node(void)
|
||||
{
|
||||
static int commit_count;
|
||||
struct commit *c = alloc_raw_commit_node();
|
||||
c->index = commit_count++;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void report(const char *name, unsigned int count, size_t size)
|
||||
{
|
||||
fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
|
||||
name, count, (uintmax_t) size);
|
||||
}
|
||||
|
||||
#define REPORT(name) \
|
||||
report(#name, name##_allocs, name##_allocs * sizeof(struct name) >> 10)
|
||||
#define REPORT(name, type) \
|
||||
report(#name, name##_allocs, name##_allocs * sizeof(type) >> 10)
|
||||
|
||||
void alloc_report(void)
|
||||
{
|
||||
REPORT(blob);
|
||||
REPORT(tree);
|
||||
REPORT(commit);
|
||||
REPORT(tag);
|
||||
REPORT(blob, struct blob);
|
||||
REPORT(tree, struct tree);
|
||||
REPORT(raw_commit, struct commit);
|
||||
REPORT(tag, struct tag);
|
||||
REPORT(object, union any_object);
|
||||
}
|
||||
|
@ -5,20 +5,18 @@
|
||||
*/
|
||||
#include "git-compat-util.h"
|
||||
#include "builtin.h"
|
||||
#include "argv-array.h"
|
||||
|
||||
int cmd_annotate(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char **nargv;
|
||||
struct argv_array args = ARGV_ARRAY_INIT;
|
||||
int i;
|
||||
nargv = xmalloc(sizeof(char *) * (argc + 2));
|
||||
|
||||
nargv[0] = "annotate";
|
||||
nargv[1] = "-c";
|
||||
argv_array_pushl(&args, "annotate", "-c", NULL);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
nargv[i+1] = argv[i];
|
||||
argv_array_push(&args, argv[i]);
|
||||
}
|
||||
nargv[argc + 1] = NULL;
|
||||
|
||||
return cmd_blame(argc + 1, nargv, prefix);
|
||||
return cmd_blame(args.argc, args.argv, prefix);
|
||||
}
|
||||
|
@ -1405,7 +1405,7 @@ static void get_commit_info(struct commit *commit,
|
||||
{
|
||||
int len;
|
||||
const char *subject, *encoding;
|
||||
char *message;
|
||||
const char *message;
|
||||
|
||||
commit_info_init(ret);
|
||||
|
||||
@ -1416,7 +1416,7 @@ static void get_commit_info(struct commit *commit,
|
||||
&ret->author_time, &ret->author_tz);
|
||||
|
||||
if (!detailed) {
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1430,7 +1430,7 @@ static void get_commit_info(struct commit *commit,
|
||||
else
|
||||
strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1));
|
||||
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2005,6 +2005,18 @@ static void append_merge_parents(struct commit_list **tail)
|
||||
strbuf_release(&line);
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't as simple as passing sb->buf and sb->len, because we
|
||||
* want to transfer ownership of the buffer to the commit (so we
|
||||
* must use detach).
|
||||
*/
|
||||
static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb)
|
||||
{
|
||||
size_t len;
|
||||
void *buf = strbuf_detach(sb, &len);
|
||||
set_commit_buffer(c, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare a dummy commit that represents the work tree (or staged) item.
|
||||
* Note that annotating work tree item never works in the reverse.
|
||||
@ -2026,7 +2038,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
|
||||
time(&now);
|
||||
commit = xcalloc(1, sizeof(*commit));
|
||||
commit = alloc_commit_node();
|
||||
commit->object.parsed = 1;
|
||||
commit->date = now;
|
||||
commit->object.type = OBJ_COMMIT;
|
||||
@ -2053,7 +2065,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
|
||||
ident, ident, path,
|
||||
(!contents_from ? path :
|
||||
(!strcmp(contents_from, "-") ? "standard input" : contents_from)));
|
||||
commit->buffer = strbuf_detach(&msg, NULL);
|
||||
set_commit_buffer_from_strbuf(commit, &msg);
|
||||
|
||||
if (!contents_from || strcmp("-", contents_from)) {
|
||||
struct stat st;
|
||||
|
@ -48,7 +48,7 @@ enum color_clean {
|
||||
CLEAN_COLOR_PROMPT = 2,
|
||||
CLEAN_COLOR_HEADER = 3,
|
||||
CLEAN_COLOR_HELP = 4,
|
||||
CLEAN_COLOR_ERROR = 5,
|
||||
CLEAN_COLOR_ERROR = 5
|
||||
};
|
||||
|
||||
#define MENU_OPTS_SINGLETON 01
|
||||
|
@ -695,7 +695,7 @@ static void write_refspec_config(const char* src_ref_prefix,
|
||||
if (option_mirror || !option_bare) {
|
||||
if (option_single_branch && !option_mirror) {
|
||||
if (option_branch) {
|
||||
if (strstr(our_head_points_at->name, "refs/tags/"))
|
||||
if (starts_with(our_head_points_at->name, "refs/tags/"))
|
||||
strbuf_addf(&value, "+%s:%s", our_head_points_at->name,
|
||||
our_head_points_at->name);
|
||||
else
|
||||
|
@ -123,8 +123,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
||||
die_errno("git commit-tree: failed to read");
|
||||
}
|
||||
|
||||
if (commit_tree(&buffer, tree_sha1, parents, commit_sha1,
|
||||
NULL, sign_commit)) {
|
||||
if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents,
|
||||
commit_sha1, NULL, sign_commit)) {
|
||||
strbuf_release(&buffer);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1672,8 +1672,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||
append_merge_tag_headers(parents, &tail);
|
||||
}
|
||||
|
||||
if (commit_tree_extended(&sb, active_cache_tree->sha1, parents, sha1,
|
||||
author_ident.buf, sign_commit, extra)) {
|
||||
if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
|
||||
parents, sha1, author_ident.buf, sign_commit, extra)) {
|
||||
rollback_index_files();
|
||||
die(_("failed to write commit object"));
|
||||
}
|
||||
|
@ -279,6 +279,7 @@ static const char *find_encoding(const char *begin, const char *end)
|
||||
static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
{
|
||||
int saved_output_format = rev->diffopt.output_format;
|
||||
const char *commit_buffer;
|
||||
const char *author, *author_end, *committer, *committer_end;
|
||||
const char *encoding, *message;
|
||||
char *reencoded = NULL;
|
||||
@ -288,7 +289,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
|
||||
|
||||
parse_commit_or_die(commit);
|
||||
author = strstr(commit->buffer, "\nauthor ");
|
||||
commit_buffer = get_commit_buffer(commit, NULL);
|
||||
author = strstr(commit_buffer, "\nauthor ");
|
||||
if (!author)
|
||||
die ("Could not find author in commit %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
@ -335,6 +337,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
? strlen(message) : 0),
|
||||
reencoded ? reencoded : message ? message : "");
|
||||
free(reencoded);
|
||||
unuse_commit_buffer(commit, commit_buffer);
|
||||
|
||||
for (i = 0, p = commit->parents; p; p = p->next) {
|
||||
int mark = get_object_mark(&p->item->object);
|
||||
|
@ -230,12 +230,14 @@ static void add_branch_desc(struct strbuf *out, const char *name)
|
||||
static void record_person(int which, struct string_list *people,
|
||||
struct commit *commit)
|
||||
{
|
||||
const char *buffer;
|
||||
char *name_buf, *name, *name_end;
|
||||
struct string_list_item *elem;
|
||||
const char *field;
|
||||
|
||||
field = (which == 'a') ? "\nauthor " : "\ncommitter ";
|
||||
name = strstr(commit->buffer, field);
|
||||
buffer = get_commit_buffer(commit, NULL);
|
||||
name = strstr(buffer, field);
|
||||
if (!name)
|
||||
return;
|
||||
name += strlen(field);
|
||||
@ -247,6 +249,7 @@ static void record_person(int which, struct string_list *people,
|
||||
if (name_end < name)
|
||||
return;
|
||||
name_buf = xmemdupz(name, name_end - name + 1);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
|
||||
elem = string_list_lookup(people, name_buf);
|
||||
if (!elem) {
|
||||
|
@ -310,8 +310,7 @@ static int fsck_obj(struct object *obj)
|
||||
if (obj->type == OBJ_COMMIT) {
|
||||
struct commit *commit = (struct commit *) obj;
|
||||
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
|
||||
if (!commit->parents && show_root)
|
||||
printf("root %s\n", sha1_to_hex(commit->object.sha1));
|
||||
|
@ -786,7 +786,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
||||
}
|
||||
if (obj->type == OBJ_COMMIT) {
|
||||
struct commit *commit = (struct commit *) obj;
|
||||
commit->buffer = NULL;
|
||||
if (detach_commit_buffer(commit, NULL) != data)
|
||||
die("BUG: parse_object_buffer transmogrified our buffer");
|
||||
}
|
||||
obj->flags |= FLAG_CHECKED;
|
||||
}
|
||||
|
@ -345,8 +345,7 @@ static int cmd_log_walk(struct rev_info *rev)
|
||||
rev->max_count++;
|
||||
if (!rev->reflog_info) {
|
||||
/* we allow cycles in reflog ancestry */
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
}
|
||||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
@ -915,9 +914,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
||||
&need_8bit_cte);
|
||||
|
||||
for (i = 0; !need_8bit_cte && i < nr; i++)
|
||||
if (has_non_ascii(list[i]->buffer))
|
||||
for (i = 0; !need_8bit_cte && i < nr; i++) {
|
||||
const char *buf = get_commit_buffer(list[i], NULL);
|
||||
if (has_non_ascii(buf))
|
||||
need_8bit_cte = 1;
|
||||
unuse_commit_buffer(list[i], buf);
|
||||
}
|
||||
|
||||
if (!branch_name)
|
||||
branch_name = find_branch_name(rev);
|
||||
@ -1504,8 +1506,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
|
||||
die(_("Failed to create output files"));
|
||||
shown = log_tree_commit(&rev, commit);
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
|
||||
/* We put one extra blank line between formatted
|
||||
* patches and this flag is used by log-tree code
|
||||
|
@ -852,8 +852,8 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
|
||||
parent->next->item = remoteheads->item;
|
||||
parent->next->next = NULL;
|
||||
prepare_to_commit(remoteheads);
|
||||
if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL,
|
||||
sign_commit))
|
||||
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent,
|
||||
result_commit, NULL, sign_commit))
|
||||
die(_("failed to write commit object"));
|
||||
finish(head, remoteheads, result_commit, "In-index merge");
|
||||
drop_save();
|
||||
@ -877,8 +877,8 @@ static int finish_automerge(struct commit *head,
|
||||
commit_list_insert(head, &parents);
|
||||
strbuf_addch(&merge_msg, '\n');
|
||||
prepare_to_commit(remoteheads);
|
||||
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
|
||||
NULL, sign_commit))
|
||||
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
|
||||
result_commit, NULL, sign_commit))
|
||||
die(_("failed to write commit object"));
|
||||
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
|
||||
finish(head, remoteheads, result_commit, buf.buf);
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
static int delta_base_offset = 1;
|
||||
static int pack_kept_objects = -1;
|
||||
static int write_bitmaps = -1;
|
||||
static char *packdir, *packtmp;
|
||||
|
||||
static const char *const git_repack_usage[] = {
|
||||
@ -27,6 +28,10 @@ static int repack_config(const char *var, const char *value, void *cb)
|
||||
pack_kept_objects = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "pack.writebitmaps")) {
|
||||
write_bitmaps = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
@ -149,7 +154,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
||||
int no_update_server_info = 0;
|
||||
int quiet = 0;
|
||||
int local = 0;
|
||||
int write_bitmap = -1;
|
||||
|
||||
struct option builtin_repack_options[] = {
|
||||
OPT_BIT('a', NULL, &pack_everything,
|
||||
@ -168,7 +172,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
||||
OPT__QUIET(&quiet, N_("be quiet")),
|
||||
OPT_BOOL('l', "local", &local,
|
||||
N_("pass --local to git-pack-objects")),
|
||||
OPT_BOOL('b', "write-bitmap-index", &write_bitmap,
|
||||
OPT_BOOL('b', "write-bitmap-index", &write_bitmaps,
|
||||
N_("write bitmap index")),
|
||||
OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
|
||||
N_("with -A, do not loosen objects older than this")),
|
||||
@ -191,7 +195,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
||||
git_repack_usage, 0);
|
||||
|
||||
if (pack_kept_objects < 0)
|
||||
pack_kept_objects = write_bitmap;
|
||||
pack_kept_objects = write_bitmaps > 0;
|
||||
|
||||
packdir = mkpathdup("%s/pack", get_object_directory());
|
||||
packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
|
||||
@ -217,9 +221,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
||||
argv_array_pushf(&cmd_args, "--no-reuse-delta");
|
||||
if (no_reuse_object)
|
||||
argv_array_pushf(&cmd_args, "--no-reuse-object");
|
||||
if (write_bitmap >= 0)
|
||||
if (write_bitmaps >= 0)
|
||||
argv_array_pushf(&cmd_args, "--%swrite-bitmap-index",
|
||||
write_bitmap ? "" : "no-");
|
||||
write_bitmaps ? "" : "no-");
|
||||
|
||||
if (pack_everything & ALL_INTO_ONE) {
|
||||
get_non_kept_pack_filenames(&existing_packs);
|
||||
|
@ -93,7 +93,7 @@ static int reset_index(const unsigned char *sha1, int reset_type, int quiet)
|
||||
static void print_new_head_line(struct commit *commit)
|
||||
{
|
||||
const char *hex, *body;
|
||||
char *msg;
|
||||
const char *msg;
|
||||
|
||||
hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
|
||||
printf(_("HEAD is now at %s"), hex);
|
||||
@ -109,7 +109,7 @@ static void print_new_head_line(struct commit *commit)
|
||||
}
|
||||
else
|
||||
printf("\n");
|
||||
logmsg_free(msg, commit);
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
|
||||
static void update_index_from_diff(struct diff_queue_struct *q,
|
||||
|
@ -106,7 +106,7 @@ static void show_commit(struct commit *commit, void *data)
|
||||
else
|
||||
putchar('\n');
|
||||
|
||||
if (revs->verbose_header && commit->buffer) {
|
||||
if (revs->verbose_header && get_cached_commit_buffer(commit, NULL)) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct pretty_print_context ctx = {0};
|
||||
ctx.abbrev = revs->abbrev;
|
||||
@ -173,8 +173,7 @@ static void finish_commit(struct commit *commit, void *data)
|
||||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
}
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
}
|
||||
|
||||
static void finish_object(struct object *obj,
|
||||
|
@ -117,4 +117,16 @@ static int stat_ ##slabname## realloc
|
||||
* catch because GCC silently parses it by default.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Statically initialize a commit slab named "var". Note that this
|
||||
* evaluates "stride" multiple times! Example:
|
||||
*
|
||||
* struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
|
||||
*
|
||||
*/
|
||||
#define COMMIT_SLAB_INIT(stride, var) { \
|
||||
COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
|
||||
(stride), 0, NULL \
|
||||
}
|
||||
|
||||
#endif /* COMMIT_SLAB_H */
|
||||
|
131
commit.c
131
commit.c
@ -17,7 +17,6 @@ static struct commit_extra_header *read_commit_extra_header_lines(const char *bu
|
||||
int save_commit_buffer = 1;
|
||||
|
||||
const char *commit_type = "commit";
|
||||
static int commit_count;
|
||||
|
||||
static struct commit *check_commit(struct object *obj,
|
||||
const unsigned char *sha1,
|
||||
@ -64,7 +63,6 @@ struct commit *lookup_commit(const unsigned char *sha1)
|
||||
struct object *obj = lookup_object(sha1);
|
||||
if (!obj) {
|
||||
struct commit *c = alloc_commit_node();
|
||||
c->index = commit_count++;
|
||||
return create_object(sha1, OBJ_COMMIT, c);
|
||||
}
|
||||
if (!obj->type)
|
||||
@ -247,6 +245,76 @@ int unregister_shallow(const unsigned char *sha1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct commit_buffer {
|
||||
void *buffer;
|
||||
unsigned long size;
|
||||
};
|
||||
define_commit_slab(buffer_slab, struct commit_buffer);
|
||||
static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
|
||||
|
||||
void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
v->buffer = buffer;
|
||||
v->size = size;
|
||||
}
|
||||
|
||||
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
return v->buffer;
|
||||
}
|
||||
|
||||
const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
const void *ret = get_cached_commit_buffer(commit, sizep);
|
||||
if (!ret) {
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
ret = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!ret)
|
||||
die("cannot read commit object %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
if (type != OBJ_COMMIT)
|
||||
die("expected commit for %s, got %s",
|
||||
sha1_to_hex(commit->object.sha1), typename(type));
|
||||
if (sizep)
|
||||
*sizep = size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unuse_commit_buffer(const struct commit *commit, const void *buffer)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
if (v->buffer != buffer)
|
||||
free((void *)buffer);
|
||||
}
|
||||
|
||||
void free_commit_buffer(struct commit *commit)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
free(v->buffer);
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
}
|
||||
|
||||
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
void *ret;
|
||||
|
||||
ret = v->buffer;
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
|
||||
{
|
||||
const char *tail = buffer;
|
||||
@ -324,7 +392,7 @@ int parse_commit(struct commit *item)
|
||||
}
|
||||
ret = parse_commit_buffer(item, buffer, size);
|
||||
if (save_commit_buffer && !ret) {
|
||||
item->buffer = buffer;
|
||||
set_commit_buffer(item, buffer, size);
|
||||
return 0;
|
||||
}
|
||||
free(buffer);
|
||||
@ -539,22 +607,12 @@ static void record_author_date(struct author_date_slab *author_date,
|
||||
struct commit *commit)
|
||||
{
|
||||
const char *buf, *line_end, *ident_line;
|
||||
char *buffer = NULL;
|
||||
const char *buffer = get_commit_buffer(commit, NULL);
|
||||
struct ident_split ident;
|
||||
char *date_end;
|
||||
unsigned long date;
|
||||
|
||||
if (!commit->buffer) {
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
buffer = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
for (buf = commit->buffer ? commit->buffer : buffer;
|
||||
buf;
|
||||
buf = line_end + 1) {
|
||||
for (buf = buffer; buf; buf = line_end + 1) {
|
||||
line_end = strchrnul(buf, '\n');
|
||||
ident_line = skip_prefix(buf, "author ");
|
||||
if (!ident_line) {
|
||||
@ -575,7 +633,7 @@ static void record_author_date(struct author_date_slab *author_date,
|
||||
*(author_date_slab_at(author_date, commit)) = date;
|
||||
|
||||
fail_exit:
|
||||
free(buffer);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
}
|
||||
|
||||
static int compare_commits_by_author_date(const void *a_, const void *b_,
|
||||
@ -1080,17 +1138,14 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_signed_commit(const unsigned char *sha1,
|
||||
int parse_signed_commit(const struct commit *commit,
|
||||
struct strbuf *payload, struct strbuf *signature)
|
||||
{
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buffer = read_sha1_file(sha1, &type, &size);
|
||||
int in_signature, saw_signature = -1;
|
||||
char *line, *tail;
|
||||
|
||||
if (!buffer || type != OBJ_COMMIT)
|
||||
goto cleanup;
|
||||
unsigned long size;
|
||||
const char *buffer = get_commit_buffer(commit, &size);
|
||||
int in_signature, saw_signature = -1;
|
||||
const char *line, *tail;
|
||||
|
||||
line = buffer;
|
||||
tail = buffer + size;
|
||||
@ -1098,7 +1153,7 @@ int parse_signed_commit(const unsigned char *sha1,
|
||||
saw_signature = 0;
|
||||
while (line < tail) {
|
||||
const char *sig = NULL;
|
||||
char *next = memchr(line, '\n', tail - line);
|
||||
const char *next = memchr(line, '\n', tail - line);
|
||||
|
||||
next = next ? next + 1 : tail;
|
||||
if (in_signature && line[0] == ' ')
|
||||
@ -1119,8 +1174,7 @@ int parse_signed_commit(const unsigned char *sha1,
|
||||
}
|
||||
line = next;
|
||||
}
|
||||
cleanup:
|
||||
free(buffer);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return saw_signature;
|
||||
}
|
||||
|
||||
@ -1211,8 +1265,7 @@ void check_commit_signature(const struct commit* commit, struct signature_check
|
||||
|
||||
sigc->result = 'N';
|
||||
|
||||
if (parse_signed_commit(commit->object.sha1,
|
||||
&payload, &signature) <= 0)
|
||||
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
||||
goto out;
|
||||
status = verify_signed_buffer(payload.buf, payload.len,
|
||||
signature.buf, signature.len,
|
||||
@ -1257,11 +1310,9 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
|
||||
{
|
||||
struct commit_extra_header *extra = NULL;
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (buffer && type == OBJ_COMMIT)
|
||||
extra = read_commit_extra_header_lines(buffer, size, exclude);
|
||||
free(buffer);
|
||||
const char *buffer = get_commit_buffer(commit, &size);
|
||||
extra = read_commit_extra_header_lines(buffer, size, exclude);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return extra;
|
||||
}
|
||||
|
||||
@ -1344,7 +1395,8 @@ void free_commit_extra_headers(struct commit_extra_header *extra)
|
||||
}
|
||||
}
|
||||
|
||||
int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
||||
int commit_tree(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit)
|
||||
{
|
||||
@ -1352,7 +1404,7 @@ int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
||||
int result;
|
||||
|
||||
append_merge_tag_headers(parents, &tail);
|
||||
result = commit_tree_extended(msg, tree, parents, ret,
|
||||
result = commit_tree_extended(msg, msg_len, tree, parents, ret,
|
||||
author, sign_commit, extra);
|
||||
free_commit_extra_headers(extra);
|
||||
return result;
|
||||
@ -1473,7 +1525,8 @@ static const char commit_utf8_warn[] =
|
||||
"You may want to amend it after fixing the message, or set the config\n"
|
||||
"variable i18n.commitencoding to the encoding your project uses.\n";
|
||||
|
||||
int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
int commit_tree_extended(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit,
|
||||
struct commit_extra_header *extra)
|
||||
@ -1484,7 +1537,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
|
||||
assert_sha1_type(tree, OBJ_TREE);
|
||||
|
||||
if (memchr(msg->buf, '\0', msg->len))
|
||||
if (memchr(msg, '\0', msg_len))
|
||||
return error("a NUL byte in commit log message not allowed.");
|
||||
|
||||
/* Not having i18n.commitencoding is the same as having utf-8 */
|
||||
@ -1523,7 +1576,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
strbuf_addch(&buffer, '\n');
|
||||
|
||||
/* And add the comment */
|
||||
strbuf_addbuf(&buffer, msg);
|
||||
strbuf_add(&buffer, msg, msg_len);
|
||||
|
||||
/* And check the encoding */
|
||||
if (encoding_is_utf8 && !verify_utf8(&buffer))
|
||||
|
54
commit.h
54
commit.h
@ -20,7 +20,6 @@ struct commit {
|
||||
unsigned long date;
|
||||
struct commit_list *parents;
|
||||
struct tree *tree;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
extern int save_commit_buffer;
|
||||
@ -51,6 +50,44 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s
|
||||
int parse_commit(struct commit *item);
|
||||
void parse_commit_or_die(struct commit *item);
|
||||
|
||||
/*
|
||||
* Associate an object buffer with the commit. The ownership of the
|
||||
* memory is handed over to the commit, and must be free()-able.
|
||||
*/
|
||||
void set_commit_buffer(struct commit *, void *buffer, unsigned long size);
|
||||
|
||||
/*
|
||||
* Get any cached object buffer associated with the commit. Returns NULL
|
||||
* if none. The resulting memory should not be freed.
|
||||
*/
|
||||
const void *get_cached_commit_buffer(const struct commit *, unsigned long *size);
|
||||
|
||||
/*
|
||||
* Get the commit's object contents, either from cache or by reading the object
|
||||
* from disk. The resulting memory should not be modified, and must be given
|
||||
* to unuse_commit_buffer when the caller is done.
|
||||
*/
|
||||
const void *get_commit_buffer(const struct commit *, unsigned long *size);
|
||||
|
||||
/*
|
||||
* Tell the commit subsytem that we are done with a particular commit buffer.
|
||||
* The commit and buffer should be the input and return value, respectively,
|
||||
* from an earlier call to get_commit_buffer. The buffer may or may not be
|
||||
* freed by this call; callers should not access the memory afterwards.
|
||||
*/
|
||||
void unuse_commit_buffer(const struct commit *, const void *buffer);
|
||||
|
||||
/*
|
||||
* Free any cached object buffer associated with the commit.
|
||||
*/
|
||||
void free_commit_buffer(struct commit *);
|
||||
|
||||
/*
|
||||
* Disassociate any cached object buffer from the commit, but do not free it.
|
||||
* The buffer (or NULL, if none) is returned.
|
||||
*/
|
||||
const void *detach_commit_buffer(struct commit *, unsigned long *sizep);
|
||||
|
||||
/* Find beginning and length of commit subject. */
|
||||
int find_commit_subject(const char *commit_buffer, const char **subject);
|
||||
|
||||
@ -115,10 +152,9 @@ struct userformat_want {
|
||||
|
||||
extern int has_non_ascii(const char *text);
|
||||
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
||||
extern char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding);
|
||||
extern void logmsg_free(char *msg, const struct commit *commit);
|
||||
extern const char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding);
|
||||
extern void get_commit_format(const char *arg, struct rev_info *);
|
||||
extern const char *format_subject(struct strbuf *sb, const char *msg,
|
||||
const char *line_separator);
|
||||
@ -261,11 +297,13 @@ struct commit_extra_header {
|
||||
extern void append_merge_tag_headers(struct commit_list *parents,
|
||||
struct commit_extra_header ***tail);
|
||||
|
||||
extern int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
||||
extern int commit_tree(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit);
|
||||
|
||||
extern int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
extern int commit_tree_extended(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit,
|
||||
struct commit_extra_header *);
|
||||
@ -287,7 +325,7 @@ struct merge_remote_desc {
|
||||
*/
|
||||
struct commit *get_merge_parent(const char *name);
|
||||
|
||||
extern int parse_signed_commit(const unsigned char *sha1,
|
||||
extern int parse_signed_commit(const struct commit *commit,
|
||||
struct strbuf *message, struct strbuf *signature);
|
||||
extern void print_commit_list(struct commit_list *list,
|
||||
const char *format_cur,
|
||||
|
32
dir.c
32
dir.c
@ -508,21 +508,25 @@ void clear_exclude_list(struct exclude_list *el)
|
||||
|
||||
static void trim_trailing_spaces(char *buf)
|
||||
{
|
||||
int i, last_space = -1, nr_spaces, len = strlen(buf);
|
||||
for (i = 0; i < len; i++)
|
||||
if (buf[i] == '\\')
|
||||
i++;
|
||||
else if (buf[i] == ' ') {
|
||||
if (last_space == -1) {
|
||||
last_space = i;
|
||||
nr_spaces = 1;
|
||||
} else
|
||||
nr_spaces++;
|
||||
} else
|
||||
last_space = -1;
|
||||
char *p, *last_space = NULL;
|
||||
|
||||
if (last_space != -1 && last_space + nr_spaces == len)
|
||||
buf[last_space] = '\0';
|
||||
for (p = buf; *p; p++)
|
||||
switch (*p) {
|
||||
case ' ':
|
||||
if (!last_space)
|
||||
last_space = p;
|
||||
break;
|
||||
case '\\':
|
||||
p++;
|
||||
if (!*p)
|
||||
return;
|
||||
/* fallthrough */
|
||||
default:
|
||||
last_space = NULL;
|
||||
}
|
||||
|
||||
if (last_space)
|
||||
*last_space = '\0';
|
||||
}
|
||||
|
||||
int add_excludes_from_file_to_list(const char *fname,
|
||||
|
13
fsck.c
13
fsck.c
@ -276,9 +276,10 @@ static int fsck_ident(const char **ident, struct object *obj, fsck_error error_f
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsck_commit(struct commit *commit, fsck_error error_func)
|
||||
static int fsck_commit_buffer(struct commit *commit, const char *buffer,
|
||||
fsck_error error_func)
|
||||
{
|
||||
const char *buffer = commit->buffer, *tmp;
|
||||
const char *tmp;
|
||||
unsigned char tree_sha1[20], sha1[20];
|
||||
struct commit_graft *graft;
|
||||
int parents = 0;
|
||||
@ -336,6 +337,14 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsck_commit(struct commit *commit, fsck_error error_func)
|
||||
{
|
||||
const char *buffer = get_commit_buffer(commit, NULL);
|
||||
int ret = fsck_commit_buffer(commit, buffer, error_func);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsck_tag(struct tag *tag, fsck_error error_func)
|
||||
{
|
||||
struct object *tagged = tag->tagged;
|
||||
|
@ -53,11 +53,12 @@ continue_merge () {
|
||||
}
|
||||
|
||||
call_merge () {
|
||||
cmt="$(cat "$state_dir/cmt.$1")"
|
||||
msgnum="$1"
|
||||
echo "$msgnum" >"$state_dir/msgnum"
|
||||
cmt="$(cat "$state_dir/cmt.$msgnum")"
|
||||
echo "$cmt" > "$state_dir/current"
|
||||
hd=$(git rev-parse --verify HEAD)
|
||||
cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
|
||||
msgnum=$(cat "$state_dir/msgnum")
|
||||
eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
|
||||
eval GITHEAD_$hd='$onto_name'
|
||||
export GITHEAD_$cmt GITHEAD_$hd
|
||||
|
@ -376,7 +376,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
|
||||
struct strbuf gpg_output = STRBUF_INIT;
|
||||
int status;
|
||||
|
||||
if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
|
||||
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
||||
goto out;
|
||||
|
||||
status = verify_signed_buffer(payload.buf, payload.len,
|
||||
@ -588,7 +588,7 @@ void show_log(struct rev_info *opt)
|
||||
show_mergetag(opt, commit);
|
||||
}
|
||||
|
||||
if (!commit->buffer)
|
||||
if (!get_cached_commit_buffer(commit, NULL))
|
||||
return;
|
||||
|
||||
if (opt->show_notes) {
|
||||
|
@ -40,7 +40,7 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
|
||||
|
||||
static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
|
||||
{
|
||||
struct commit *commit = xcalloc(1, sizeof(struct commit));
|
||||
struct commit *commit = alloc_commit_node();
|
||||
struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
|
||||
|
||||
desc->name = comment;
|
||||
@ -190,9 +190,11 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
|
||||
printf(_("(bad commit)\n"));
|
||||
else {
|
||||
const char *title;
|
||||
int len = find_commit_subject(commit->buffer, &title);
|
||||
const char *msg = get_commit_buffer(commit, NULL);
|
||||
int len = find_commit_subject(msg, &title);
|
||||
if (len)
|
||||
printf("%.*s\n", len, title);
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ int notes_cache_write(struct notes_cache *c)
|
||||
{
|
||||
unsigned char tree_sha1[20];
|
||||
unsigned char commit_sha1[20];
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
|
||||
if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref)
|
||||
return -1;
|
||||
@ -57,9 +56,8 @@ int notes_cache_write(struct notes_cache *c)
|
||||
|
||||
if (write_notes_tree(&c->tree, tree_sha1))
|
||||
return -1;
|
||||
strbuf_attach(&msg, c->validity,
|
||||
strlen(c->validity), strlen(c->validity) + 1);
|
||||
if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
|
||||
if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
|
||||
commit_sha1, NULL, NULL) < 0)
|
||||
return -1;
|
||||
if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
|
||||
0, QUIET_ON_ERR) < 0)
|
||||
|
@ -644,7 +644,8 @@ int notes_merge(struct notes_merge_options *o,
|
||||
struct commit_list *parents = NULL;
|
||||
commit_list_insert(remote, &parents); /* LIFO order */
|
||||
commit_list_insert(local, &parents);
|
||||
create_notes_commit(local_tree, parents, &o->commit_msg,
|
||||
create_notes_commit(local_tree, parents,
|
||||
o->commit_msg.buf, o->commit_msg.len,
|
||||
result_sha1);
|
||||
}
|
||||
|
||||
@ -671,8 +672,8 @@ int notes_merge_commit(struct notes_merge_options *o,
|
||||
DIR *dir;
|
||||
struct dirent *e;
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
char *msg = strstr(partial_commit->buffer, "\n\n");
|
||||
struct strbuf sb_msg = STRBUF_INIT;
|
||||
const char *buffer = get_commit_buffer(partial_commit, NULL);
|
||||
const char *msg = strstr(buffer, "\n\n");
|
||||
int baselen;
|
||||
|
||||
strbuf_addstr(&path, git_path(NOTES_MERGE_WORKTREE));
|
||||
@ -719,9 +720,9 @@ int notes_merge_commit(struct notes_merge_options *o,
|
||||
strbuf_setlen(&path, baselen);
|
||||
}
|
||||
|
||||
strbuf_attach(&sb_msg, msg, strlen(msg), strlen(msg) + 1);
|
||||
create_notes_commit(partial_tree, partial_commit->parents, &sb_msg,
|
||||
result_sha1);
|
||||
create_notes_commit(partial_tree, partial_commit->parents,
|
||||
msg, strlen(msg), result_sha1);
|
||||
unuse_commit_buffer(partial_commit, buffer);
|
||||
if (o->verbosity >= 4)
|
||||
printf("Finalized notes merge commit: %s\n",
|
||||
sha1_to_hex(result_sha1));
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include "notes-utils.h"
|
||||
|
||||
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
||||
const struct strbuf *msg, unsigned char *result_sha1)
|
||||
const char *msg, size_t msg_len,
|
||||
unsigned char *result_sha1)
|
||||
{
|
||||
unsigned char tree_sha1[20];
|
||||
|
||||
@ -25,7 +26,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
||||
/* else: t->ref points to nothing, assume root/orphan commit */
|
||||
}
|
||||
|
||||
if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
|
||||
if (commit_tree(msg, msg_len, tree_sha1, parents, result_sha1, NULL, NULL))
|
||||
die("Failed to commit notes tree to database");
|
||||
}
|
||||
|
||||
@ -46,7 +47,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
|
||||
if (buf.buf[buf.len - 1] != '\n')
|
||||
strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
|
||||
|
||||
create_notes_commit(t, NULL, &buf, commit_sha1);
|
||||
create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1);
|
||||
strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
|
||||
update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, DIE_ON_ERR);
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* The resulting commit SHA1 is stored in result_sha1.
|
||||
*/
|
||||
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
||||
const struct strbuf *msg, unsigned char *result_sha1);
|
||||
const char *msg, size_t msg_len, unsigned char *result_sha1);
|
||||
|
||||
void commit_notes(struct notes_tree *t, const char *msg);
|
||||
|
||||
|
4
object.c
4
object.c
@ -197,8 +197,8 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
|
||||
if (commit) {
|
||||
if (parse_commit_buffer(commit, buffer, size))
|
||||
return NULL;
|
||||
if (!commit->buffer) {
|
||||
commit->buffer = buffer;
|
||||
if (!get_cached_commit_buffer(commit, NULL)) {
|
||||
set_commit_buffer(commit, buffer, size);
|
||||
*eaten_p = 1;
|
||||
}
|
||||
obj = &commit->object;
|
||||
|
54
pretty.c
54
pretty.c
@ -274,7 +274,7 @@ static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
|
||||
|
||||
enum rfc2047_type {
|
||||
RFC2047_SUBJECT,
|
||||
RFC2047_ADDRESS,
|
||||
RFC2047_ADDRESS
|
||||
};
|
||||
|
||||
static int is_rfc2047_special(char ch, enum rfc2047_type type)
|
||||
@ -606,29 +606,16 @@ static char *replace_encoding_header(char *buf, const char *encoding)
|
||||
return strbuf_detach(&tmp, NULL);
|
||||
}
|
||||
|
||||
char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding)
|
||||
const char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding)
|
||||
{
|
||||
static const char *utf8 = "UTF-8";
|
||||
const char *use_encoding;
|
||||
char *encoding;
|
||||
char *msg = commit->buffer;
|
||||
const char *msg = get_commit_buffer(commit, NULL);
|
||||
char *out;
|
||||
|
||||
if (!msg) {
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
|
||||
msg = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!msg)
|
||||
die("Cannot read commit object %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
if (type != OBJ_COMMIT)
|
||||
die("Expected commit for '%s', got %s",
|
||||
sha1_to_hex(commit->object.sha1), typename(type));
|
||||
}
|
||||
|
||||
if (!output_encoding || !*output_encoding) {
|
||||
if (commit_encoding)
|
||||
*commit_encoding =
|
||||
@ -652,12 +639,13 @@ char *logmsg_reencode(const struct commit *commit,
|
||||
* Otherwise, we still want to munge the encoding header in the
|
||||
* result, which will be done by modifying the buffer. If we
|
||||
* are using a fresh copy, we can reuse it. But if we are using
|
||||
* the cached copy from commit->buffer, we need to duplicate it
|
||||
* to avoid munging commit->buffer.
|
||||
* the cached copy from get_commit_buffer, we need to duplicate it
|
||||
* to avoid munging the cached copy.
|
||||
*/
|
||||
out = msg;
|
||||
if (out == commit->buffer)
|
||||
out = xstrdup(out);
|
||||
if (msg == get_cached_commit_buffer(commit, NULL))
|
||||
out = xstrdup(msg);
|
||||
else
|
||||
out = (char *)msg;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
@ -667,8 +655,8 @@ char *logmsg_reencode(const struct commit *commit,
|
||||
* copy, we can free it.
|
||||
*/
|
||||
out = reencode_string(msg, output_encoding, use_encoding);
|
||||
if (out && msg != commit->buffer)
|
||||
free(msg);
|
||||
if (out)
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -687,12 +675,6 @@ char *logmsg_reencode(const struct commit *commit,
|
||||
return out ? out : msg;
|
||||
}
|
||||
|
||||
void logmsg_free(char *msg, const struct commit *commit)
|
||||
{
|
||||
if (msg != commit->buffer)
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static int mailmap_name(const char **email, size_t *email_len,
|
||||
const char **name, size_t *name_len)
|
||||
{
|
||||
@ -796,7 +778,7 @@ struct format_commit_context {
|
||||
struct signature_check signature_check;
|
||||
enum flush_type flush_type;
|
||||
enum trunc_type truncate;
|
||||
char *message;
|
||||
const char *message;
|
||||
char *commit_encoding;
|
||||
size_t width, indent1, indent2;
|
||||
int auto_color;
|
||||
@ -1267,6 +1249,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
|
||||
if (c->signature_check.key)
|
||||
strbuf_addstr(sb, c->signature_check.key);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
@ -1536,7 +1520,7 @@ void format_commit_message(const struct commit *commit,
|
||||
}
|
||||
|
||||
free(context.commit_encoding);
|
||||
logmsg_free(context.message, commit);
|
||||
unuse_commit_buffer(commit, context.message);
|
||||
free(context.signature_check.gpg_output);
|
||||
free(context.signature_check.signer);
|
||||
}
|
||||
@ -1705,7 +1689,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
|
||||
unsigned long beginning_of_body;
|
||||
int indent = 4;
|
||||
const char *msg;
|
||||
char *reencoded;
|
||||
const char *reencoded;
|
||||
const char *encoding;
|
||||
int need_8bit_cte = pp->need_8bit_cte;
|
||||
|
||||
@ -1772,7 +1756,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
|
||||
if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
|
||||
strbuf_addch(sb, '\n');
|
||||
|
||||
logmsg_free(reencoded, commit);
|
||||
unuse_commit_buffer(commit, reencoded);
|
||||
}
|
||||
|
||||
void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
|
||||
|
15
revision.c
15
revision.c
@ -2791,7 +2791,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
|
||||
{
|
||||
int retval;
|
||||
const char *encoding;
|
||||
char *message;
|
||||
const char *message;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
|
||||
@ -2833,14 +2833,21 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
|
||||
format_display_notes(commit->object.sha1, &buf, encoding, 1);
|
||||
}
|
||||
|
||||
/* Find either in the original commit message, or in the temporary */
|
||||
/*
|
||||
* Find either in the original commit message, or in the temporary.
|
||||
* Note that we cast away the constness of "message" here. It is
|
||||
* const because it may come from the cached commit buffer. That's OK,
|
||||
* because we know that it is modifiable heap memory, and that while
|
||||
* grep_buffer may modify it for speed, it will restore any
|
||||
* changes before returning.
|
||||
*/
|
||||
if (buf.len)
|
||||
retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
|
||||
else
|
||||
retval = grep_buffer(&opt->grep_filter,
|
||||
message, strlen(message));
|
||||
(char *)message, strlen(message));
|
||||
strbuf_release(&buf);
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
49
sequencer.c
49
sequencer.c
@ -116,39 +116,23 @@ static const char *action_name(const struct replay_opts *opts)
|
||||
return opts->action == REPLAY_REVERT ? "revert" : "cherry-pick";
|
||||
}
|
||||
|
||||
static char *get_encoding(const char *message);
|
||||
|
||||
struct commit_message {
|
||||
char *parent_label;
|
||||
const char *label;
|
||||
const char *subject;
|
||||
char *reencoded_message;
|
||||
const char *message;
|
||||
};
|
||||
|
||||
static int get_message(struct commit *commit, struct commit_message *out)
|
||||
{
|
||||
const char *encoding;
|
||||
const char *abbrev, *subject;
|
||||
int abbrev_len, subject_len;
|
||||
char *q;
|
||||
|
||||
if (!commit->buffer)
|
||||
return -1;
|
||||
encoding = get_encoding(commit->buffer);
|
||||
if (!encoding)
|
||||
encoding = "UTF-8";
|
||||
if (!git_commit_encoding)
|
||||
git_commit_encoding = "UTF-8";
|
||||
|
||||
out->reencoded_message = NULL;
|
||||
out->message = commit->buffer;
|
||||
if (same_encoding(encoding, git_commit_encoding))
|
||||
out->reencoded_message = reencode_string(commit->buffer,
|
||||
git_commit_encoding, encoding);
|
||||
if (out->reencoded_message)
|
||||
out->message = out->reencoded_message;
|
||||
|
||||
out->message = logmsg_reencode(commit, NULL, git_commit_encoding);
|
||||
abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
|
||||
abbrev_len = strlen(abbrev);
|
||||
|
||||
@ -167,29 +151,10 @@ static int get_message(struct commit *commit, struct commit_message *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_message(struct commit_message *msg)
|
||||
static void free_message(struct commit *commit, struct commit_message *msg)
|
||||
{
|
||||
free(msg->parent_label);
|
||||
free(msg->reencoded_message);
|
||||
}
|
||||
|
||||
static char *get_encoding(const char *message)
|
||||
{
|
||||
const char *p = message, *eol;
|
||||
|
||||
while (*p && *p != '\n') {
|
||||
for (eol = p + 1; *eol && *eol != '\n'; eol++)
|
||||
; /* do nothing */
|
||||
if (starts_with(p, "encoding ")) {
|
||||
char *result = xmalloc(eol - 8 - p);
|
||||
strlcpy(result, p + 9, eol - 8 - p);
|
||||
return result;
|
||||
}
|
||||
p = eol;
|
||||
if (*p == '\n')
|
||||
p++;
|
||||
}
|
||||
return NULL;
|
||||
unuse_commit_buffer(commit, msg->message);
|
||||
}
|
||||
|
||||
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
|
||||
@ -485,7 +450,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||
unsigned char head[20];
|
||||
struct commit *base, *next, *parent;
|
||||
const char *base_label, *next_label;
|
||||
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
|
||||
struct commit_message msg = { NULL, NULL, NULL, NULL };
|
||||
char *defmsg = NULL;
|
||||
struct strbuf msgbuf = STRBUF_INIT;
|
||||
int res, unborn = 0, allow;
|
||||
@ -650,7 +615,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||
res = run_git_commit(defmsg, opts, allow);
|
||||
|
||||
leave:
|
||||
free_message(&msg);
|
||||
free_message(commit, &msg);
|
||||
free(defmsg);
|
||||
|
||||
return res;
|
||||
@ -697,10 +662,12 @@ static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
|
||||
int subject_len;
|
||||
|
||||
for (cur = todo_list; cur; cur = cur->next) {
|
||||
const char *commit_buffer = get_commit_buffer(cur->item, NULL);
|
||||
sha1_abbrev = find_unique_abbrev(cur->item->object.sha1, DEFAULT_ABBREV);
|
||||
subject_len = find_commit_subject(cur->item->buffer, &subject);
|
||||
subject_len = find_commit_subject(commit_buffer, &subject);
|
||||
strbuf_addf(buf, "%s %s %.*s\n", action_str, sha1_abbrev,
|
||||
subject_len, subject);
|
||||
unuse_commit_buffer(cur->item, commit_buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -315,7 +315,8 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, int
|
||||
* thing twice, or object directory itself.
|
||||
*/
|
||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||
if (!memcmp(ent->base, alt->base, pfxlen)) {
|
||||
if (pfxlen == alt->name - alt->base - 1 &&
|
||||
!memcmp(ent->base, alt->base, pfxlen)) {
|
||||
free(ent);
|
||||
return -1;
|
||||
}
|
||||
|
18
sha1_name.c
18
sha1_name.c
@ -862,27 +862,17 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
|
||||
commit_list_insert(l->item, &backup);
|
||||
}
|
||||
while (list) {
|
||||
char *p, *to_free = NULL;
|
||||
const char *p, *buf;
|
||||
struct commit *commit;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
int matches;
|
||||
|
||||
commit = pop_most_recent_commit(&list, ONELINE_SEEN);
|
||||
if (!parse_object(commit->object.sha1))
|
||||
continue;
|
||||
if (commit->buffer)
|
||||
p = commit->buffer;
|
||||
else {
|
||||
p = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!p)
|
||||
continue;
|
||||
to_free = p;
|
||||
}
|
||||
|
||||
p = strstr(p, "\n\n");
|
||||
buf = get_commit_buffer(commit, NULL);
|
||||
p = strstr(buf, "\n\n");
|
||||
matches = p && !regexec(®ex, p + 2, 0, NULL, 0);
|
||||
free(to_free);
|
||||
unuse_commit_buffer(commit, buf);
|
||||
|
||||
if (matches) {
|
||||
hashcpy(sha1, commit->object.sha1);
|
||||
|
@ -806,4 +806,29 @@ test_expect_success !MINGW 'quoting allows trailing whitespace' '
|
||||
test_cmp err.expect err
|
||||
'
|
||||
|
||||
test_expect_success NOT_MINGW,NOT_CYGWIN 'correct handling of backslashes' '
|
||||
rm -rf whitespace &&
|
||||
mkdir whitespace &&
|
||||
>"whitespace/trailing 1 " &&
|
||||
>"whitespace/trailing 2 \\\\" &&
|
||||
>"whitespace/trailing 3 \\\\" &&
|
||||
>"whitespace/trailing 4 \\ " &&
|
||||
>"whitespace/trailing 5 \\ \\ " &&
|
||||
>"whitespace/trailing 6 \\a\\" &&
|
||||
>whitespace/untracked &&
|
||||
sed -e "s/Z$//" >ignore <<-\EOF &&
|
||||
whitespace/trailing 1 \ Z
|
||||
whitespace/trailing 2 \\\\Z
|
||||
whitespace/trailing 3 \\\\ Z
|
||||
whitespace/trailing 4 \\\ Z
|
||||
whitespace/trailing 5 \\ \\\ Z
|
||||
whitespace/trailing 6 \\a\\Z
|
||||
EOF
|
||||
echo whitespace/untracked >expect &&
|
||||
>err.expect &&
|
||||
git ls-files -o -X ignore whitespace >actual 2>err &&
|
||||
test_cmp expect actual &&
|
||||
test_cmp err.expect err
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -33,6 +33,7 @@ test_expect_success setup '
|
||||
tr "[a-z]" "[A-Z]" <original >newfile &&
|
||||
git add newfile &&
|
||||
git commit -a -m"side edits further." &&
|
||||
git branch second-side &&
|
||||
|
||||
tr "[a-m]" "[A-M]" <original >newfile &&
|
||||
rm -f original &&
|
||||
@ -41,6 +42,7 @@ test_expect_success setup '
|
||||
git branch test-rebase side &&
|
||||
git branch test-rebase-pick side &&
|
||||
git branch test-reference-pick side &&
|
||||
git branch test-conflicts side &&
|
||||
git checkout -b test-merge side
|
||||
'
|
||||
|
||||
@ -138,4 +140,17 @@ test_expect_success 'rebase -s funny -Xopt' '
|
||||
test -f funny.was.run
|
||||
'
|
||||
|
||||
test_expect_success 'rebase --skip works with two conflicts in a row' '
|
||||
git checkout second-side &&
|
||||
tr "[A-Z]" "[a-z]" <newfile >tmp &&
|
||||
mv tmp newfile &&
|
||||
git commit -a -m"edit conflicting with side" &&
|
||||
tr "[d-f]" "[D-F]" <newfile >tmp &&
|
||||
mv tmp newfile &&
|
||||
git commit -a -m"another edit conflicting with side" &&
|
||||
test_must_fail git rebase --merge test-conflicts &&
|
||||
test_must_fail git rebase --skip &&
|
||||
git rebase --skip
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -468,4 +468,10 @@ test_expect_success 'single-character name is parsed correctly' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'unused %G placeholders are passed through' '
|
||||
echo "%GX %G" >expect &&
|
||||
git log -1 --format="%GX %G" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -426,10 +426,10 @@ test_expect_success SANITY 'removal failure' '
|
||||
|
||||
mkdir foo &&
|
||||
touch foo/bar &&
|
||||
test_when_finished "chmod 755 foo" &&
|
||||
(exec <foo/bar &&
|
||||
chmod 0 foo &&
|
||||
test_must_fail git clean -f -d &&
|
||||
chmod 755 foo)
|
||||
test_must_fail git clean -f -d)
|
||||
'
|
||||
|
||||
test_expect_success 'nested git work tree' '
|
||||
|
@ -43,31 +43,44 @@ test_expect_success GPG 'create signed commits' '
|
||||
|
||||
test_tick && git rebase -f HEAD^^ && git tag sixth-signed HEAD^ &&
|
||||
git tag seventh-signed
|
||||
|
||||
echo 8 >file && test_tick && git commit -a -m eighth -SB7227189 &&
|
||||
git tag eighth-signed-alt
|
||||
'
|
||||
|
||||
test_expect_success GPG 'show signatures' '
|
||||
(
|
||||
for commit in initial second merge fourth-signed fifth-signed sixth-signed master
|
||||
for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
|
||||
do
|
||||
git show --pretty=short --show-signature $commit >actual &&
|
||||
grep "Good signature from" actual || exit 1
|
||||
! grep "BAD signature from" actual || exit 1
|
||||
echo $commit OK
|
||||
grep "Good signature from" actual &&
|
||||
! grep "BAD signature from" actual &&
|
||||
echo $commit OK || exit 1
|
||||
done
|
||||
) &&
|
||||
(
|
||||
for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
|
||||
do
|
||||
git show --pretty=short --show-signature $commit >actual &&
|
||||
grep "Good signature from" actual && exit 1
|
||||
! grep "BAD signature from" actual || exit 1
|
||||
echo $commit OK
|
||||
! grep "Good signature from" actual &&
|
||||
! grep "BAD signature from" actual &&
|
||||
echo $commit OK || exit 1
|
||||
done
|
||||
) &&
|
||||
(
|
||||
for commit in eighth-signed-alt
|
||||
do
|
||||
git show --pretty=short --show-signature $commit >actual &&
|
||||
grep "Good signature from" actual &&
|
||||
! grep "BAD signature from" actual &&
|
||||
grep "not certified" actual &&
|
||||
echo $commit OK || exit 1
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success GPG 'detect fudged signature' '
|
||||
git cat-file commit master >raw &&
|
||||
git cat-file commit seventh-signed >raw &&
|
||||
|
||||
sed -e "s/seventh/7th forged/" raw >forged1 &&
|
||||
git hash-object -w -t commit forged1 >forged1.commit &&
|
||||
@ -77,7 +90,7 @@ test_expect_success GPG 'detect fudged signature' '
|
||||
'
|
||||
|
||||
test_expect_success GPG 'detect fudged signature with NUL' '
|
||||
git cat-file commit master >raw &&
|
||||
git cat-file commit seventh-signed >raw &&
|
||||
cat raw >forged2 &&
|
||||
echo Qwik | tr "Q" "\000" >>forged2 &&
|
||||
git hash-object -w -t commit forged2 >forged2.commit &&
|
||||
@ -94,4 +107,44 @@ test_expect_success GPG 'amending already signed commit' '
|
||||
! grep "BAD signature from" actual
|
||||
'
|
||||
|
||||
test_expect_success GPG 'show good signature with custom format' '
|
||||
cat >expect <<-\EOF &&
|
||||
G
|
||||
13B6F51ECDDE430D
|
||||
C O Mitter <committer@example.com>
|
||||
EOF
|
||||
git log -1 --format="%G?%n%GK%n%GS" sixth-signed >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GPG 'show bad signature with custom format' '
|
||||
cat >expect <<-\EOF &&
|
||||
B
|
||||
13B6F51ECDDE430D
|
||||
C O Mitter <committer@example.com>
|
||||
EOF
|
||||
git log -1 --format="%G?%n%GK%n%GS" $(cat forged1.commit) >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GPG 'show unknown signature with custom format' '
|
||||
cat >expect <<-\EOF &&
|
||||
U
|
||||
61092E85B7227189
|
||||
Eris Discordia <discord@example.net>
|
||||
EOF
|
||||
git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GPG 'show lack of signature with custom format' '
|
||||
cat >expect <<-\EOF &&
|
||||
N
|
||||
|
||||
|
||||
EOF
|
||||
git log -1 --format="%G?%n%GK%n%GS" seventh-unsigned >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -35,9 +35,25 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
|
||||
test -z "$found_duplicate_object"
|
||||
'
|
||||
|
||||
test_expect_success 'writing bitmaps can duplicate .keep objects' '
|
||||
test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '
|
||||
# build on $objsha1, $packsha1, and .keep state from previous
|
||||
git repack -Adl &&
|
||||
git repack -Adbl &&
|
||||
test_when_finished "found_duplicate_object=" &&
|
||||
for p in .git/objects/pack/*.idx; do
|
||||
idx=$(basename $p)
|
||||
test "pack-$packsha1.idx" = "$idx" && continue
|
||||
if git verify-pack -v $p | egrep "^$objsha1"; then
|
||||
found_duplicate_object=1
|
||||
echo "DUPLICATE OBJECT FOUND"
|
||||
break
|
||||
fi
|
||||
done &&
|
||||
test "$found_duplicate_object" = 1
|
||||
'
|
||||
|
||||
test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
|
||||
# build on $objsha1, $packsha1, and .keep state from previous
|
||||
git -c pack.writebitmaps=true repack -Adl &&
|
||||
test_when_finished "found_duplicate_object=" &&
|
||||
for p in .git/objects/pack/*.idx; do
|
||||
idx=$(basename $p)
|
||||
|
Reference in New Issue
Block a user