Merge branch 'jk/prefix-filename'
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Mar 2017 17:59:26 +0000 (10:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Mar 2017 17:59:26 +0000 (10:59 -0700)
Code clean-up with minor bugfixes.

* jk/prefix-filename:
bundle: use prefix_filename with bundle path
prefix_filename: simplify windows #ifdef
prefix_filename: return newly allocated string
prefix_filename: drop length parameter
prefix_filename: move docstring to header file
hash-object: fix buffer reuse with --path in a subdirectory

17 files changed:
abspath.c
apply.c
builtin/bundle.c
builtin/config.c
builtin/hash-object.c
builtin/log.c
builtin/mailinfo.c
builtin/merge-file.c
builtin/rev-parse.c
builtin/worktree.c
cache.h
diff-no-index.c
diff.c
parse-options.c
setup.c
t/t1007-hash-object.sh
worktree.c
index b02e068aa347db683b00246061b48bfafabbc1c0..7f1cfe97929ea33efb81adfcc97b82f334dccb3d 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -246,29 +246,21 @@ char *absolute_pathdup(const char *path)
        return strbuf_detach(&sb, NULL);
 }
 
-/*
- * Unlike prefix_path, this should be used if the named file does
- * not have to interact with index entry; i.e. name of a random file
- * on the filesystem.
- */
-const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
+char *prefix_filename(const char *pfx, const char *arg)
 {
-       static struct strbuf path = STRBUF_INIT;
-#ifndef GIT_WINDOWS_NATIVE
-       if (!pfx_len || is_absolute_path(arg))
-               return arg;
-       strbuf_reset(&path);
-       strbuf_add(&path, pfx, pfx_len);
-       strbuf_addstr(&path, arg);
-#else
-       /* don't add prefix to absolute paths, but still replace '\' by '/' */
-       strbuf_reset(&path);
-       if (is_absolute_path(arg))
+       struct strbuf path = STRBUF_INIT;
+       size_t pfx_len = pfx ? strlen(pfx) : 0;
+
+       if (!pfx_len)
+               ; /* nothing to prefix */
+       else if (is_absolute_path(arg))
                pfx_len = 0;
-       else if (pfx_len)
+       else
                strbuf_add(&path, pfx, pfx_len);
+
        strbuf_addstr(&path, arg);
+#ifdef GIT_WINDOWS_NATIVE
        convert_slashes(path.buf + pfx_len);
 #endif
-       return path.buf;
+       return strbuf_detach(&path, NULL);
 }
diff --git a/apply.c b/apply.c
index 0e2caeab9cc523364e0cfbb8cbbb5aba1a0a58ee..e6dbab26ad54b9a3af06f6adad928c6e1526db58 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -2046,7 +2046,7 @@ static void prefix_one(struct apply_state *state, char **name)
        char *old_name = *name;
        if (!old_name)
                return;
-       *name = xstrdup(prefix_filename(state->prefix, state->prefix_length, *name));
+       *name = prefix_filename(state->prefix, *name);
        free(old_name);
 }
 
@@ -4805,6 +4805,7 @@ int apply_all_patches(struct apply_state *state,
 
        for (i = 0; i < argc; i++) {
                const char *arg = argv[i];
+               char *to_free = NULL;
                int fd;
 
                if (!strcmp(arg, "-")) {
@@ -4814,21 +4815,21 @@ int apply_all_patches(struct apply_state *state,
                        errs |= res;
                        read_stdin = 0;
                        continue;
-               } else if (0 < state->prefix_length)
-                       arg = prefix_filename(state->prefix,
-                                             state->prefix_length,
-                                             arg);
+               } else
+                       arg = to_free = prefix_filename(state->prefix, arg);
 
                fd = open(arg, O_RDONLY);
                if (fd < 0) {
                        error(_("can't open patch '%s': %s"), arg, strerror(errno));
                        res = -128;
+                       free(to_free);
                        goto end;
                }
                read_stdin = 0;
                set_default_whitespace_mode(state);
                res = apply_patch(state, fd, arg, options);
                close(fd);
+               free(to_free);
                if (res < 0)
                        goto end;
                errs |= res;
index 4883a435a9afc607618d34c9b61b218eeda7de45..d0de59b94ff23eebe03984dc670babf793bdd5ff 100644 (file)
@@ -20,21 +20,15 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
        struct bundle_header header;
        const char *cmd, *bundle_file;
        int bundle_fd = -1;
-       char buffer[PATH_MAX];
 
        if (argc < 3)
                usage(builtin_bundle_usage);
 
        cmd = argv[1];
-       bundle_file = argv[2];
+       bundle_file = prefix_filename(prefix, argv[2]);
        argc -= 2;
        argv += 2;
 
-       if (prefix && bundle_file[0] != '/') {
-               snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file);
-               bundle_file = buffer;
-       }
-
        memset(&header, 0, sizeof(header));
        if (strcmp(cmd, "create") && (bundle_fd =
                                read_bundle_header(bundle_file, &header)) < 0)
index 05843a0f96e4dc0dbf9fbc7310039794b57947e7..4f49a0edb9071f4f63e97dfae902ff7a0aa51ee9 100644 (file)
@@ -527,9 +527,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        else if (given_config_source.file) {
                if (!is_absolute_path(given_config_source.file) && prefix)
                        given_config_source.file =
-                               xstrdup(prefix_filename(prefix,
-                                                       strlen(prefix),
-                                                       given_config_source.file));
+                               prefix_filename(prefix, given_config_source.file);
        }
 
        if (respect_includes == -1)
index 9028e1fdccea2ad44a76792adc6e335fb44cfb5c..bbeaf20bcca1ae1e9bfa55b5a8e4adbed83c00e8 100644 (file)
@@ -102,7 +102,6 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
        int i;
-       int prefix_length = -1;
        const char *errstr = NULL;
 
        argc = parse_options(argc, argv, NULL, hash_object_options,
@@ -113,9 +112,8 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
        else
                prefix = setup_git_directory_gently(&nongit);
 
-       prefix_length = prefix ? strlen(prefix) : 0;
        if (vpath && prefix)
-               vpath = prefix_filename(prefix, prefix_length, vpath);
+               vpath = xstrdup(prefix_filename(prefix, vpath));
 
        git_config(git_default_config, NULL);
 
@@ -144,11 +142,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 
        for (i = 0 ; i < argc; i++) {
                const char *arg = argv[i];
+               char *to_free = NULL;
 
-               if (0 <= prefix_length)
-                       arg = prefix_filename(prefix, prefix_length, arg);
+               if (prefix)
+                       arg = to_free = prefix_filename(prefix, arg);
                hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
                            flags, literally);
+               free(to_free);
        }
 
        if (stdin_paths)
index 281af8c1ecb04c7be05d9a17a1d5f3bd43420c85..670229cbb4c2a80e7389bc9d65f92455d1d34427 100644 (file)
@@ -1084,8 +1084,7 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
        if (!output_directory)
                return prefix;
 
-       return xstrdup(prefix_filename(prefix, outdir_offset,
-                                      output_directory));
+       return prefix_filename(prefix, output_directory);
 }
 
 static const char * const builtin_format_patch_usage[] = {
index e3b62f2fc744d340de5e3d9efad12b5de93cd55c..cfb667a594c8452b8f4259bb3da1976965906f95 100644 (file)
 static const char mailinfo_usage[] =
        "git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info";
 
-static char *prefix_copy(const char *prefix, const char *filename)
-{
-       if (!prefix || is_absolute_path(filename))
-               return xstrdup(filename);
-       return xstrdup(prefix_filename(prefix, strlen(prefix), filename));
-}
-
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
        const char *def_charset;
@@ -60,8 +53,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
        mi.input = stdin;
        mi.output = stdout;
 
-       msgfile = prefix_copy(prefix, argv[1]);
-       patchfile = prefix_copy(prefix, argv[2]);
+       msgfile = prefix_filename(prefix, argv[1]);
+       patchfile = prefix_filename(prefix, argv[2]);
 
        status = !!mailinfo(&mi, msgfile, patchfile);
        clear_mailinfo(&mi);
index 13e22a2f0be73ec7e521a02d1f36c414e77a8700..47dde7c39c922c77bf388e87db27618d09f5bb74 100644 (file)
@@ -28,7 +28,6 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
        xmparam_t xmp = {{0}};
        int ret = 0, i = 0, to_stdout = 0;
        int quiet = 0;
-       int prefixlen = 0;
        struct option options[] = {
                OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
                OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
@@ -65,15 +64,19 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
                        return error_errno("failed to redirect stderr to /dev/null");
        }
 
-       if (prefix)
-               prefixlen = strlen(prefix);
-
        for (i = 0; i < 3; i++) {
-               const char *fname = prefix_filename(prefix, prefixlen, argv[i]);
+               char *fname;
+               int ret;
+
                if (!names[i])
                        names[i] = argv[i];
-               if (read_mmfile(mmfs + i, fname))
+
+               fname = prefix_filename(prefix, argv[i]);
+               ret = read_mmfile(mmfs + i, fname);
+               free(fname);
+               if (ret)
                        return -1;
+
                if (mmfs[i].size > MAX_XDIFF_SIZE ||
                    buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
                        return error("Cannot merge binary files: %s",
@@ -90,7 +93,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 
        if (ret >= 0) {
                const char *filename = argv[0];
-               const char *fpath = prefix_filename(prefix, prefixlen, argv[0]);
+               char *fpath = prefix_filename(prefix, argv[0]);
                FILE *f = to_stdout ? stdout : fopen(fpath, "wb");
 
                if (!f)
@@ -102,6 +105,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
                else if (fclose(f))
                        ret = error_errno("Could not close %s", filename);
                free(result.ptr);
+               free(fpath);
        }
 
        if (ret > 127)
index 1e5bdea0d5ba598b4191238fee761295bd8523ab..9e53a1a7ca4a4ffa0bd810673d432c6f2449f5a5 100644 (file)
@@ -228,9 +228,9 @@ static int show_file(const char *arg, int output_prefix)
        if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
                if (output_prefix) {
                        const char *prefix = startup_info->prefix;
-                       show(prefix_filename(prefix,
-                                            prefix ? strlen(prefix) : 0,
-                                            arg));
+                       char *fname = prefix_filename(prefix, arg);
+                       show(fname);
+                       free(fname);
                } else
                        show(arg);
                return 1;
index 831fe058a53da95643b1a93038f576d5bffea7ef..9993ded41aaaaa9a9291bf51b9949a97418a5e76 100644 (file)
@@ -318,7 +318,8 @@ static int add(int ac, const char **av, const char *prefix)
 {
        struct add_opts opts;
        const char *new_branch_force = NULL;
-       const char *path, *branch;
+       char *path;
+       const char *branch;
        struct option options[] = {
                OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")),
                OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
@@ -338,7 +339,7 @@ static int add(int ac, const char **av, const char *prefix)
        if (ac < 1 || ac > 2)
                usage_with_options(worktree_usage, options);
 
-       path = prefix_filename(prefix, strlen(prefix), av[0]);
+       path = prefix_filename(prefix, av[0]);
        branch = ac < 2 ? "HEAD" : av[1];
 
        if (!strcmp(branch, "-"))
diff --git a/cache.h b/cache.h
index 2214d52f6127f20ad9788402b0e448977db615c5..db4120c233535e363cb9c368056ee83bf0b113db 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -529,7 +529,19 @@ extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
 extern char *prefix_path(const char *prefix, int len, const char *path);
 extern char *prefix_path_gently(const char *prefix, int len, int *remaining, const char *path);
-extern const char *prefix_filename(const char *prefix, int len, const char *path);
+
+/*
+ * Concatenate "prefix" (if len is non-zero) and "path", with no
+ * connecting characters (so "prefix" should end with a "/").
+ * Unlike prefix_path, this should be used if the named file does
+ * not have to interact with index entry; i.e. name of a random file
+ * on the filesystem.
+ *
+ * The return value is always a newly allocated string (even if the
+ * prefix was empty).
+ */
+extern char *prefix_filename(const char *prefix, const char *path);
+
 extern int check_filename(const char *prefix, const char *name);
 extern void verify_filename(const char *prefix,
                            const char *name,
index df762fd0f7d1ec74175a42de07b064107d3a601a..79229382b06cefc98aa8926065f0fb999ad1da2e 100644 (file)
@@ -236,7 +236,7 @@ static void fixup_paths(const char **path, struct strbuf *replacement)
 void diff_no_index(struct rev_info *revs,
                   int argc, const char **argv)
 {
-       int i, prefixlen;
+       int i;
        const char *paths[2];
        struct strbuf replacement = STRBUF_INIT;
        const char *prefix = revs->prefix;
@@ -257,7 +257,6 @@ void diff_no_index(struct rev_info *revs,
                }
        }
 
-       prefixlen = prefix ? strlen(prefix) : 0;
        for (i = 0; i < 2; i++) {
                const char *p = argv[argc - 2 + i];
                if (!strcmp(p, "-"))
@@ -266,8 +265,8 @@ void diff_no_index(struct rev_info *revs,
                         * path that is "-", spell it as "./-".
                         */
                        p = file_from_standard_input;
-               else if (prefixlen)
-                       p = xstrdup(prefix_filename(prefix, prefixlen, p));
+               else if (prefix)
+                       p = prefix_filename(prefix, p);
                paths[i] = p;
        }
 
diff --git a/diff.c b/diff.c
index a628ac3a95108ca79aef0b41b7051ab2fcbe693a..58cb72d7e72a85bad9ae9fe8a198fef1cb1b15f8 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -4023,8 +4023,7 @@ int diff_opt_parse(struct diff_options *options,
        else if (!strcmp(arg, "--pickaxe-regex"))
                options->pickaxe_opts |= DIFF_PICKAXE_REGEX;
        else if ((argcount = short_opt('O', av, &optarg))) {
-               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
-               options->orderfile = xstrdup(path);
+               options->orderfile = prefix_filename(prefix, optarg);
                return argcount;
        }
        else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
@@ -4071,13 +4070,14 @@ int diff_opt_parse(struct diff_options *options,
        else if (!strcmp(arg, "--no-function-context"))
                DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
-               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               char *path = prefix_filename(prefix, optarg);
                options->file = fopen(path, "w");
                if (!options->file)
                        die_errno("Could not open '%s'", path);
                options->close_file = 1;
                if (options->use_color != GIT_COLOR_ALWAYS)
                        options->use_color = GIT_COLOR_NEVER;
+               free(path);
                return argcount;
        } else
                return 0;
index 4fbe924a5de27d04b271a11a2ae040e817483951..a23a1e67f04f8072bea357cbed34fdc1b39ab7ae 100644 (file)
@@ -40,7 +40,7 @@ static void fix_filename(const char *prefix, const char **file)
        if (!file || !*file || !prefix || is_absolute_path(*file)
            || !strcmp("-", *file))
                return;
-       *file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
+       *file = prefix_filename(prefix, *file);
 }
 
 static int opt_command_mode_error(const struct option *opt,
diff --git a/setup.c b/setup.c
index 64f922a9378cc48c72b9173e7c45296bdb885678..5c7946d2b45f067049e11347cca1cedc9790e228 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -135,6 +135,7 @@ int path_inside_repo(const char *prefix, const char *path)
 int check_filename(const char *prefix, const char *arg)
 {
        const char *name;
+       char *to_free = NULL;
        struct stat st;
 
        if (starts_with(arg, ":/")) {
@@ -142,13 +143,17 @@ int check_filename(const char *prefix, const char *arg)
                        return 1;
                name = arg + 2;
        } else if (prefix)
-               name = prefix_filename(prefix, strlen(prefix), arg);
+               name = to_free = prefix_filename(prefix, arg);
        else
                name = arg;
-       if (!lstat(name, &st))
+       if (!lstat(name, &st)) {
+               free(to_free);
                return 1; /* file exists */
-       if (errno == ENOENT || errno == ENOTDIR)
+       }
+       if (errno == ENOENT || errno == ENOTDIR) {
+               free(to_free);
                return 0; /* file does not exist */
+       }
        die_errno("failed to stat '%s'", arg);
 }
 
index c5245c5cb4c1c086b6fe7205f34b9b5ca53e2e59..532682f51c4f9cefc34a44cf7e7f4231c60b7f65 100755 (executable)
@@ -134,6 +134,16 @@ test_expect_success 'gitattributes also work in a subdirectory' '
        )
 '
 
+test_expect_success '--path works in a subdirectory' '
+       (
+               cd subdir &&
+               path1_sha=$(git hash-object --path=../file1 ../file0) &&
+               path0_sha=$(git hash-object --path=../file0 ../file1) &&
+               test "$file0_sha" = "$path0_sha" &&
+               test "$file1_sha" = "$path1_sha"
+       )
+'
+
 test_expect_success 'check that --no-filters option works' '
        nofilters_file1=$(git hash-object --no-filters file1) &&
        test "$file0_sha" = "$nofilters_file1" &&
index fa7bc67a50a6d52116b0ca994b473668998f1c3f..bae787cf8d7e968e8d5118bf54f17112c0229bf5 100644 (file)
@@ -250,16 +250,19 @@ struct worktree *find_worktree(struct worktree **list,
 {
        struct worktree *wt;
        char *path;
+       char *to_free = NULL;
 
        if ((wt = find_worktree_by_suffix(list, arg)))
                return wt;
 
-       arg = prefix_filename(prefix, strlen(prefix), arg);
+       if (prefix)
+               arg = to_free = prefix_filename(prefix, arg);
        path = real_pathdup(arg, 1);
        for (; *list; list++)
                if (!fspathcmp(path, real_path((*list)->path)))
                        break;
        free(path);
+       free(to_free);
        return *list;
 }