Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Documentation/RelNotes/2.54.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ UI, Workflows & Features
* The reference-transaction hook was taught to be triggered before
taking locks on references in the "preparing" phase.

* "git apply" now reports the name of the input file along with the
line number when it encounters a corrupt patch, and correctly
resets the line counter when processing multiple patch files.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand Down Expand Up @@ -239,6 +243,16 @@ Performance, Internal Implementation, Development Support etc.
* Uses of prio_queue as a LIFO stack of commits have been written
with commit_stack.

* The cleanup of remaining bitmaps in "ahead_behind()" has been
simplified.

* split-index.c has been updated to not use the global the_repository
and the_hash_algo variables.

* The unsigned integer that is used as an bitset to specify the kind
of branches interpret_branch_name() function has been changed to
use a dedicated enum type.


Fixes since v2.53
-----------------
Expand Down
100 changes: 74 additions & 26 deletions apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

struct gitdiff_data {
struct strbuf *root;
const char *patch_input_file;
int linenr;
int p_value;
};
Expand Down Expand Up @@ -900,7 +901,8 @@ static int parse_traditional_patch(struct apply_state *state,
}
}
if (!name)
return error(_("unable to find filename in patch at line %d"), state->linenr);
return error(_("unable to find filename in patch at %s:%d"),
state->patch_input_file, state->linenr);

return 0;
}
Expand Down Expand Up @@ -937,20 +939,35 @@ static int gitdiff_verify_name(struct gitdiff_data *state,

if (*name) {
char *another;
if (isnull)
if (isnull) {
if (state->patch_input_file)
return error(_("git apply: bad git-diff - expected /dev/null, got %s at %s:%d"),
*name, state->patch_input_file, state->linenr);
return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
*name, state->linenr);
}
another = find_name(state->root, line, NULL, state->p_value, TERM_TAB);
if (!another || strcmp(another, *name)) {
free(another);
if (state->patch_input_file)
return error((side == DIFF_NEW_NAME) ?
_("git apply: bad git-diff - inconsistent new filename at %s:%d") :
_("git apply: bad git-diff - inconsistent old filename at %s:%d"),
state->patch_input_file, state->linenr);
return error((side == DIFF_NEW_NAME) ?
_("git apply: bad git-diff - inconsistent new filename on line %d") :
_("git apply: bad git-diff - inconsistent old filename on line %d"), state->linenr);
_("git apply: bad git-diff - inconsistent new filename on line %d") :
_("git apply: bad git-diff - inconsistent old filename on line %d"),
state->linenr);
}
free(another);
} else {
if (!is_dev_null(line))
return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
if (!is_dev_null(line)) {
if (state->patch_input_file)
return error(_("git apply: bad git-diff - expected /dev/null at %s:%d"),
state->patch_input_file, state->linenr);
return error(_("git apply: bad git-diff - expected /dev/null on line %d"),
state->linenr);
}
}

return 0;
Expand All @@ -974,12 +991,19 @@ static int gitdiff_newname(struct gitdiff_data *state,
DIFF_NEW_NAME);
}

static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
static int parse_mode_line(const char *line,
const char *patch_input_file,
int linenr,
unsigned int *mode)
{
char *end;
*mode = strtoul(line, &end, 8);
if (end == line || !isspace(*end))
if (end == line || !isspace(*end)) {
if (patch_input_file)
return error(_("invalid mode at %s:%d: %s"),
patch_input_file, linenr, line);
return error(_("invalid mode on line %d: %s"), linenr, line);
}
*mode = canon_mode(*mode);
return 0;
}
Expand All @@ -988,14 +1012,16 @@ static int gitdiff_oldmode(struct gitdiff_data *state,
const char *line,
struct patch *patch)
{
return parse_mode_line(line, state->linenr, &patch->old_mode);
return parse_mode_line(line, state->patch_input_file, state->linenr,
&patch->old_mode);
}

static int gitdiff_newmode(struct gitdiff_data *state,
const char *line,
struct patch *patch)
{
return parse_mode_line(line, state->linenr, &patch->new_mode);
return parse_mode_line(line, state->patch_input_file, state->linenr,
&patch->new_mode);
}

static int gitdiff_delete(struct gitdiff_data *state,
Expand Down Expand Up @@ -1314,6 +1340,7 @@ static int check_header_line(int linenr, struct patch *patch)
}

int parse_git_diff_header(struct strbuf *root,
const char *patch_input_file,
int *linenr,
int p_value,
const char *line,
Expand Down Expand Up @@ -1345,6 +1372,7 @@ int parse_git_diff_header(struct strbuf *root,
size -= len;
(*linenr)++;
parse_hdr_state.root = root;
parse_hdr_state.patch_input_file = patch_input_file;
parse_hdr_state.linenr = *linenr;
parse_hdr_state.p_value = p_value;

Expand Down Expand Up @@ -1382,6 +1410,7 @@ int parse_git_diff_header(struct strbuf *root,
int res;
if (len < oplen || memcmp(p->str, line, oplen))
continue;
parse_hdr_state.linenr = *linenr;
res = p->fn(&parse_hdr_state, line + oplen, patch);
if (res < 0)
return -1;
Expand All @@ -1396,21 +1425,33 @@ int parse_git_diff_header(struct strbuf *root,
done:
if (!patch->old_name && !patch->new_name) {
if (!patch->def_name) {
error(Q_("git diff header lacks filename information when removing "
"%d leading pathname component (line %d)",
"git diff header lacks filename information when removing "
"%d leading pathname components (line %d)",
parse_hdr_state.p_value),
parse_hdr_state.p_value, *linenr);
if (patch_input_file)
error(Q_("git diff header lacks filename information when removing "
"%d leading pathname component at %s:%d",
"git diff header lacks filename information when removing "
"%d leading pathname components at %s:%d",
parse_hdr_state.p_value),
parse_hdr_state.p_value, patch_input_file, *linenr);
else
error(Q_("git diff header lacks filename information when removing "
"%d leading pathname component (line %d)",
"git diff header lacks filename information when removing "
"%d leading pathname components (line %d)",
parse_hdr_state.p_value),
parse_hdr_state.p_value, *linenr);
return -128;
}
patch->old_name = xstrdup(patch->def_name);
patch->new_name = xstrdup(patch->def_name);
}
if ((!patch->new_name && !patch->is_delete) ||
(!patch->old_name && !patch->is_new)) {
error(_("git diff header lacks filename information "
"(line %d)"), *linenr);
if (patch_input_file)
error(_("git diff header lacks filename information at %s:%d"),
patch_input_file, *linenr);
else
error(_("git diff header lacks filename information (line %d)"),
*linenr);
return -128;
}
patch->is_toplevel_relative = 1;
Expand Down Expand Up @@ -1577,8 +1618,9 @@ static int find_header(struct apply_state *state,
struct fragment dummy;
if (parse_fragment_header(line, len, &dummy) < 0)
continue;
error(_("patch fragment without header at line %d: %.*s"),
state->linenr, (int)len-1, line);
error(_("patch fragment without header at %s:%d: %.*s"),
state->patch_input_file, state->linenr,
(int)len-1, line);
return -128;
}

Expand All @@ -1590,7 +1632,9 @@ static int find_header(struct apply_state *state,
* or mode change, so we handle that specially
*/
if (!memcmp("diff --git ", line, 11)) {
int git_hdr_len = parse_git_diff_header(&state->root, &state->linenr,
int git_hdr_len = parse_git_diff_header(&state->root,
state->patch_input_file,
&state->linenr,
state->p_value, line, len,
size, patch);
if (git_hdr_len < 0)
Expand Down Expand Up @@ -1875,7 +1919,8 @@ static int parse_single_patch(struct apply_state *state,
len = parse_fragment(state, line, size, patch, fragment);
if (len <= 0) {
free(fragment);
return error(_("corrupt patch at line %d"), state->linenr);
return error(_("corrupt patch at %s:%d"),
state->patch_input_file, state->linenr);
}
fragment->patch = line;
fragment->size = len;
Expand Down Expand Up @@ -2065,8 +2110,8 @@ static struct fragment *parse_binary_hunk(struct apply_state *state,
corrupt:
free(data);
*status_p = -1;
error(_("corrupt binary patch at line %d: %.*s"),
state->linenr-1, llen-1, buffer);
error(_("corrupt binary patch at %s:%d: %.*s"),
state->patch_input_file, state->linenr-1, llen-1, buffer);
return NULL;
}

Expand Down Expand Up @@ -2102,7 +2147,8 @@ static int parse_binary(struct apply_state *state,
forward = parse_binary_hunk(state, &buffer, &size, &status, &used);
if (!forward && !status)
/* there has to be one hunk (forward hunk) */
return error(_("unrecognized binary patch at line %d"), state->linenr-1);
return error(_("unrecognized binary patch at %s:%d"),
state->patch_input_file, state->linenr-1);
if (status)
/* otherwise we already gave an error message */
return status;
Expand Down Expand Up @@ -2264,7 +2310,8 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si
*/
if ((state->apply || state->check) &&
(!patch->is_binary && !metadata_changes(patch))) {
error(_("patch with only garbage at line %d"), state->linenr);
error(_("patch with only garbage at %s:%d"),
state->patch_input_file, state->linenr);
return -128;
}
}
Expand Down Expand Up @@ -4825,6 +4872,7 @@ static int apply_patch(struct apply_state *state,
int flush_attributes = 0;

state->patch_input_file = filename;
state->linenr = 1;
if (read_patch_file(&buf, fd) < 0)
return -128;
offset = 0;
Expand Down
1 change: 1 addition & 0 deletions apply.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ int check_apply_state(struct apply_state *state, int force_apply);
* Returns -1 on failure, the length of the parsed header otherwise.
*/
int parse_git_diff_header(struct strbuf *root,
const char *patch_input_file,
int *linenr,
int p_value,
const char *line,
Expand Down
2 changes: 1 addition & 1 deletion builtin/branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
int ret = 0;
int remote_branch = 0;
struct strbuf bname = STRBUF_INIT;
unsigned allowed_interpret;
enum interpret_branch_kind allowed_interpret;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
struct string_list_item *item;
int branch_name_pos;
Expand Down
6 changes: 2 additions & 4 deletions commit-reach.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,10 +1117,8 @@ void ahead_behind(struct repository *r,

/* STALE is used here, PARENT2 is used by insert_no_dup(). */
repo_clear_commit_marks(r, PARENT2 | STALE);
while (prio_queue_peek(&queue)) {
struct commit *c = prio_queue_get(&queue);
free_bit_array(c);
}
for (size_t i = 0; i < queue.nr; i++)
free_bit_array(queue.array[i].data);
clear_bit_arrays(&bit_arrays);
clear_prio_queue(&queue);
}
Expand Down
6 changes: 4 additions & 2 deletions object-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -1664,7 +1664,8 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str

static int reinterpret(struct repository *r,
const char *name, int namelen, int len,
struct strbuf *buf, unsigned allowed)
struct strbuf *buf,
enum interpret_branch_kind allowed)
{
/* we have extra data, which might need further processing */
struct strbuf tmp = STRBUF_INIT;
Expand Down Expand Up @@ -1696,7 +1697,8 @@ static void set_shortened_ref(struct repository *r, struct strbuf *buf, const ch
free(s);
}

static int branch_interpret_allowed(const char *refname, unsigned allowed)
static int branch_interpret_allowed(const char *refname,
enum interpret_branch_kind allowed)
{
if (!allowed)
return 1;
Expand Down
11 changes: 7 additions & 4 deletions object-name.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,20 @@ int set_disambiguate_hint_config(const char *var, const char *value);
* If the input was ok but there are not N branch switches in the
* reflog, it returns 0.
*/
#define INTERPRET_BRANCH_LOCAL (1<<0)
#define INTERPRET_BRANCH_REMOTE (1<<1)
#define INTERPRET_BRANCH_HEAD (1<<2)
enum interpret_branch_kind {
INTERPRET_BRANCH_LOCAL = (1 << 0),
INTERPRET_BRANCH_REMOTE = (1 << 1),
INTERPRET_BRANCH_HEAD = (1 << 2),
};

struct interpret_branch_name_options {
/*
* If "allowed" is non-zero, it is a treated as a bitfield of allowable
* expansions: local branches ("refs/heads/"), remote branches
* ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
* allowed, even ones to refs outside of those namespaces.
*/
unsigned allowed;
enum interpret_branch_kind allowed;

/*
* If ^{upstream} or ^{push} (or equivalent) is requested, and the
Expand Down
2 changes: 1 addition & 1 deletion range-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static int read_patches(const char *range, struct string_list *list,
if (eol)
*eol = '\n';
orig_len = len;
len = parse_git_diff_header(&root, &linenr, 0, line,
len = parse_git_diff_header(&root, NULL, &linenr, 0, line,
len, size, &patch);
if (len < 0) {
error(_("could not parse git header '%.*s'"),
Expand Down
3 changes: 2 additions & 1 deletion refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@ static char *substitute_branch_name(struct repository *r,
return NULL;
}

void copy_branchname(struct strbuf *sb, const char *name, unsigned allowed)
void copy_branchname(struct strbuf *sb, const char *name,
enum interpret_branch_kind allowed)
{
int len = strlen(name);
struct interpret_branch_name_options options = {
Expand Down
3 changes: 2 additions & 1 deletion refs.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef REFS_H
#define REFS_H

#include "object-name.h"
#include "commit.h"
#include "repository.h"
#include "repo-settings.h"
Expand Down Expand Up @@ -225,7 +226,7 @@ char *repo_default_branch_name(struct repository *r, int quiet);
* repo_interpret_branch_name() for details.
*/
void copy_branchname(struct strbuf *sb, const char *name,
unsigned allowed);
enum interpret_branch_kind allowed);

/*
* Like copy_branchname() above, but confirm that the result is
Expand Down
Loading