From 28f704433b949bfd7fe43a15aab0023b114fe706 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 23 Sep 2015 10:38:51 -0400 Subject: [PATCH] patch_parse: use names from `diff --git` header When a text file is added or deleted, use the file names from the `diff --git` header instead of the `---` or `+++` lines. This is for compatibility with git. --- src/diff_print.c | 1 - src/patch_parse.c | 61 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/diff_print.c b/src/diff_print.c index 7c9af2449..29ffcdd51 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -282,7 +282,6 @@ static int diff_print_oid_range( git_oid_tostr(start_oid, oid_strlen, &delta->old_file.id); git_oid_tostr(end_oid, oid_strlen, &delta->new_file.id); - /* TODO: Match git diff more closely */ if (delta->old_file.mode == delta->new_file.mode) { git_buf_printf(out, "index %s..%s %o\n", start_oid, end_oid, delta->old_file.mode); diff --git a/src/patch_parse.c b/src/patch_parse.c index a450ecc05..f375688af 100644 --- a/src/patch_parse.c +++ b/src/patch_parse.c @@ -628,6 +628,49 @@ done: return error; } +static int check_filenames( + git_patch_parsed *patch, + patch_parse_ctx *ctx) +{ + /* For modechange only patches, it does not include filenames; + * instead we need to use the paths in the diff --git header. + */ + if (!patch->base.delta->old_file.path && + !patch->base.delta->new_file.path) { + + if (!ctx->header_old_path || !ctx->header_new_path) + return parse_err("git diff header lacks old / new paths"); + + patch->base.delta->old_file.path = ctx->header_old_path; + ctx->header_old_path = NULL; + + patch->base.delta->new_file.path = ctx->header_new_path; + ctx->header_new_path = NULL; + } + + /* For additions that have a `diff --git` header, set the old path + * to the path from the header, not `/dev/null`. + */ + if (patch->base.delta->status == GIT_DELTA_ADDED && + ctx->header_old_path) { + git__free((char *)patch->base.delta->old_file.path); + patch->base.delta->old_file.path = ctx->header_old_path; + ctx->header_old_path = NULL; + } + + /* For deletes, set the new path to the path from the + * `diff --git` header, not `/dev/null`. + */ + if (patch->base.delta->status == GIT_DELTA_DELETED && + ctx->header_new_path) { + git__free((char *)patch->base.delta->new_file.path); + patch->base.delta->new_file.path = ctx->header_new_path; + ctx->header_new_path = NULL; + } + + return 0; +} + static int parsed_patch_header( git_patch_parsed *patch, patch_parse_ctx *ctx) @@ -667,23 +710,7 @@ static int parsed_patch_header( if ((error = parse_header_git(patch, ctx)) < 0) goto done; - /* For modechange only patches, it does not include filenames; - * instead we need to use the paths in the diff --git header. - */ - if (!patch->base.delta->old_file.path && - !patch->base.delta->new_file.path) { - - if (!ctx->header_old_path || !ctx->header_new_path) { - error = parse_err("git diff header lacks old / new paths"); - goto done; - } - - patch->base.delta->old_file.path = ctx->header_old_path; - ctx->header_old_path = NULL; - - patch->base.delta->new_file.path = ctx->header_new_path; - ctx->header_new_path = NULL; - } + error = check_filenames(patch, ctx); goto done; }