diff options
Diffstat (limited to 'builtin')
| -rw-r--r-- | builtin/annotate.c | 20 | ||||
| -rw-r--r-- | builtin/checkout.c | 2 | ||||
| -rw-r--r-- | builtin/clone.c | 27 | ||||
| -rw-r--r-- | builtin/config.c | 4 | ||||
| -rw-r--r-- | builtin/difftool.c | 6 | ||||
| -rw-r--r-- | builtin/fetch-pack.c | 14 | ||||
| -rw-r--r-- | builtin/fetch.c | 3 | ||||
| -rw-r--r-- | builtin/fsmonitor--daemon.c | 7 | ||||
| -rw-r--r-- | builtin/gc.c | 189 | ||||
| -rw-r--r-- | builtin/help.c | 16 | ||||
| -rw-r--r-- | builtin/index-pack.c | 7 | ||||
| -rw-r--r-- | builtin/ls-remote.c | 1 | ||||
| -rw-r--r-- | builtin/pack-redundant.c | 40 | ||||
| -rw-r--r-- | builtin/pull.c | 11 | ||||
| -rw-r--r-- | builtin/push.c | 10 | ||||
| -rw-r--r-- | builtin/receive-pack.c | 5 | ||||
| -rw-r--r-- | builtin/repack.c | 57 | ||||
| -rw-r--r-- | builtin/revert.c | 17 | ||||
| -rw-r--r-- | builtin/send-pack.c | 3 | ||||
| -rw-r--r-- | builtin/sparse-checkout.c | 5 | ||||
| -rw-r--r-- | builtin/stash.c | 4 | ||||
| -rw-r--r-- | builtin/submodule--helper.c | 41 | ||||
| -rw-r--r-- | builtin/worktree.c | 16 |
23 files changed, 370 insertions, 135 deletions
diff --git a/builtin/annotate.c b/builtin/annotate.c index ce3dfaafb2..7f754f2309 100644 --- a/builtin/annotate.c +++ b/builtin/annotate.c @@ -14,13 +14,23 @@ int cmd_annotate(int argc, struct repository *repo) { struct strvec args = STRVEC_INIT; - int i; + const char **args_copy; + int ret; strvec_pushl(&args, "annotate", "-c", NULL); - - for (i = 1; i < argc; i++) { + for (int i = 1; i < argc; i++) strvec_push(&args, argv[i]); - } - return cmd_blame(args.nr, args.v, prefix, repo); + /* + * `cmd_blame()` ends up modifying the array, which causes memory leaks + * if we didn't copy the array here. + */ + CALLOC_ARRAY(args_copy, args.nr + 1); + COPY_ARRAY(args_copy, args.v, args.nr); + + ret = cmd_blame(args.nr, args_copy, prefix, repo); + + strvec_clear(&args); + free(args_copy); + return ret; } diff --git a/builtin/checkout.c b/builtin/checkout.c index 9c30000d3a..c449558e66 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1716,7 +1716,7 @@ static struct option *add_common_switch_branch_options( N_("update ignored files (default)"), PARSE_OPT_NOCOMPLETE), OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees, - N_("do not check if another worktree is holding the given ref")), + N_("do not check if another worktree is using this branch")), OPT_END() }; struct option *newopts = parse_options_concat(prevopts, options); diff --git a/builtin/clone.c b/builtin/clone.c index e77339c847..59fcb317a6 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -1403,8 +1403,17 @@ int cmd_clone(int argc, * data from the --bundle-uri option. */ if (bundle_uri) { + struct remote_state *state; int has_heuristic = 0; + /* + * We need to save the remote state as our remote's lifetime is + * tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); @@ -1413,6 +1422,10 @@ int cmd_clone(int argc, bundle_uri); else if (has_heuristic) git_config_set_gently("fetch.bundleuri", bundle_uri); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { /* * Populate transport->got_remote_bundle_uri and @@ -1422,12 +1435,26 @@ int cmd_clone(int argc, if (transport->bundles && hashmap_get_size(&transport->bundles->bundles)) { + struct remote_state *state; + + /* + * We need to save the remote state as our remote's + * lifetime is tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); else if (fetch_bundle_list(the_repository, transport->bundles)) warning(_("failed to fetch advertised bundles")); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { clear_bundle_list(transport->bundles); FREE_AND_NULL(transport->bundles); diff --git a/builtin/config.c b/builtin/config.c index d8fd3def0e..cba7022108 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -19,7 +19,7 @@ static const char *const builtin_config_usage[] = { N_("git config list [<file-option>] [<display-option>] [--includes]"), N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"), N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), N_("git config rename-section [<file-option>] <old-name> <new-name>"), N_("git config remove-section [<file-option>] <name>"), N_("git config edit [<file-option>]"), @@ -43,7 +43,7 @@ static const char *const builtin_config_set_usage[] = { }; static const char *const builtin_config_unset_usage[] = { - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), NULL }; diff --git a/builtin/difftool.c b/builtin/difftool.c index 4b416743ff..5772e82106 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -662,6 +662,12 @@ finish: if (fp) fclose(fp); + hashmap_clear_and_free(&working_tree_dups, struct working_tree_entry, entry); + hashmap_clear_and_free(&wt_modified, struct path_entry, entry); + hashmap_clear_and_free(&tmp_modified, struct path_entry, entry); + hashmap_clear_and_free(&submodules, struct pair_entry, entry); + hashmap_clear_and_free(&symlinks2, struct pair_entry, entry); + release_index(&wtindex); free(lbase_dir); free(rbase_dir); strbuf_release(&info); diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 49222a36fa..62e8c3aa6b 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -53,6 +53,7 @@ int cmd_fetch_pack(int argc, struct ref *fetched_refs = NULL, *remote_refs = NULL; const char *dest = NULL; struct ref **sought = NULL; + struct ref **sought_to_free = NULL; int nr_sought = 0, alloc_sought = 0; int fd[2]; struct string_list pack_lockfiles = STRING_LIST_INIT_DUP; @@ -243,6 +244,13 @@ int cmd_fetch_pack(int argc, BUG("unknown protocol version"); } + /* + * Create a shallow copy of `sought` so that we can free all of its entries. + * This is because `fetch_pack()` will modify the array to evict some + * entries, but won't free those. + */ + DUP_ARRAY(sought_to_free, sought, nr_sought); + fetched_refs = fetch_pack(&args, fd, remote_refs, sought, nr_sought, &shallow, pack_lockfiles_ptr, version); @@ -280,9 +288,13 @@ int cmd_fetch_pack(int argc, oid_to_hex(&ref->old_oid), ref->name); for (size_t i = 0; i < nr_sought; i++) - free_one_ref(sought[i]); + free_one_ref(sought_to_free[i]); + free(sought_to_free); free(sought); free_refs(fetched_refs); free_refs(remote_refs); + list_objects_filter_release(&args.filter_options); + oid_array_clear(&shallow); + string_list_clear(&pack_lockfiles, 0); return ret; } diff --git a/builtin/fetch.c b/builtin/fetch.c index c900f57721..d9027e4dc9 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -456,6 +456,7 @@ static void filter_prefetch_refspec(struct refspec *rs) free(rs->items[i].src); free(rs->items[i].dst); + free(rs->raw[i]); for (j = i + 1; j < rs->nr; j++) { rs->items[j - 1] = rs->items[j]; @@ -1980,6 +1981,8 @@ static int fetch_multiple(struct string_list *list, int max_children, strvec_pushl(&argv, "-c", "fetch.bundleURI=", "fetch", "--append", "--no-auto-gc", "--no-write-commit-graph", NULL); + for (i = 0; i < server_options.nr; i++) + strvec_pushf(&argv, "--server-option=%s", server_options.items[i].string); add_options_to_argv(&argv, config); if (max_children != 1 && list->nr != 1) { diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index dce8a3b248..f3f6bd330b 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1208,9 +1208,9 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state) * system event listener thread so that we have the IPC handle * before we need it. */ - if (ipc_server_run_async(&state->ipc_server_data, - state->path_ipc.buf, &ipc_opts, - handle_client, state)) + if (ipc_server_init_async(&state->ipc_server_data, + state->path_ipc.buf, &ipc_opts, + handle_client, state)) return error_errno( _("could not start IPC thread pool on '%s'"), state->path_ipc.buf); @@ -1314,6 +1314,7 @@ static int fsmonitor_run_daemon(void) strbuf_reset(&state.path_gitdir_watch); strbuf_addstr(&state.path_gitdir_watch, absolute_path(repo_get_git_dir(the_repository))); + strbuf_strip_suffix(&state.path_gitdir_watch, "/."); state.nr_paths_watching = 2; } diff --git a/builtin/gc.c b/builtin/gc.c index c3894fb6bd..d52735354c 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1478,9 +1478,9 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts, static void initialize_maintenance_strategy(void) { - char *config_str; + const char *config_str; - if (git_config_get_string("maintenance.strategy", &config_str)) + if (git_config_get_string_tmp("maintenance.strategy", &config_str)) return; if (!strcasecmp(config_str, "incremental")) { @@ -1768,6 +1768,42 @@ static const char *get_frequency(enum schedule_priority schedule) } } +static const char *extraconfig[] = { + "credential.interactive=false", + "core.askPass=true", /* 'true' returns success, but no output. */ + NULL +}; + +static const char *get_extra_config_parameters(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) + strbuf_addf(&builder, "-c %s ", *s); + + result = strbuf_detach(&builder, NULL); + return result; +} + +static const char *get_extra_launchctl_strings(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) { + strbuf_addstr(&builder, "<string>-c</string>\n"); + strbuf_addf(&builder, "<string>%s</string>\n", *s); + } + + result = strbuf_detach(&builder, NULL); + return result; +} + /* * get_schedule_cmd` reads the GIT_TEST_MAINT_SCHEDULER environment variable * to mock the schedulers that `git maintenance start` rely on. @@ -1782,39 +1818,43 @@ static const char *get_frequency(enum schedule_priority schedule) * * If $GIT_TEST_MAINT_SCHEDULER is set, return true. * In this case, the *cmd value is read as input. * - * * if the input value *cmd is the key of one of the comma-separated list - * item, then *is_available is set to true and *cmd is modified and becomes + * * if the input value cmd is the key of one of the comma-separated list + * item, then *is_available is set to true and *out is set to * the mock command. * * * if the input value *cmd isn’t the key of any of the comma-separated list - * item, then *is_available is set to false. + * item, then *is_available is set to false and *out is set to the original + * command. * * Ex.: * GIT_TEST_MAINT_SCHEDULER not set * +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ - * | "foo" | false | "foo" (unchanged) | (unchanged) | + * | "foo" | false | "foo" (allocated) | (unchanged) | * +-------+-------------+-------------------+---------------+ * * GIT_TEST_MAINT_SCHEDULER set to “foo:./mock_foo.sh,bar:./mock_bar.sh” * +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ * | "foo" | true | "./mock.foo.sh" | true | - * | "qux" | true | "qux" (unchanged) | false | + * | "qux" | true | "qux" (allocated) | false | * +-------+-------------+-------------------+---------------+ */ -static int get_schedule_cmd(const char **cmd, int *is_available) +static int get_schedule_cmd(const char *cmd, int *is_available, char **out) { char *testing = xstrdup_or_null(getenv("GIT_TEST_MAINT_SCHEDULER")); struct string_list_item *item; struct string_list list = STRING_LIST_INIT_NODUP; - if (!testing) + if (!testing) { + if (out) + *out = xstrdup(cmd); return 0; + } if (is_available) *is_available = 0; @@ -1826,16 +1866,22 @@ static int get_schedule_cmd(const char **cmd, int *is_available) if (string_list_split_in_place(&pair, item->string, ":", 2) != 2) continue; - if (!strcmp(*cmd, pair.items[0].string)) { - *cmd = pair.items[1].string; + if (!strcmp(cmd, pair.items[0].string)) { + if (out) + *out = xstrdup(pair.items[1].string); if (is_available) *is_available = 1; - string_list_clear(&list, 0); - UNLEAK(testing); - return 1; + string_list_clear(&pair, 0); + goto out; } + + string_list_clear(&pair, 0); } + if (out) + *out = xstrdup(cmd); + +out: string_list_clear(&list, 0); free(testing); return 1; @@ -1852,9 +1898,8 @@ static int get_random_minute(void) static int is_launchctl_available(void) { - const char *cmd = "launchctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("launchctl", &is_available, NULL)) return is_available; #ifdef __APPLE__ @@ -1892,12 +1937,12 @@ static char *launchctl_get_uid(void) static int launchctl_boot_plist(int enable, const char *filename) { - const char *cmd = "launchctl"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; char *uid = launchctl_get_uid(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, enable ? "bootstrap" : "bootout", uid, filename, NULL); @@ -1910,6 +1955,7 @@ static int launchctl_boot_plist(int enable, const char *filename) result = finish_command(&child); + free(cmd); free(uid); return result; } @@ -1961,10 +2007,10 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit static unsigned long lock_file_timeout_ms = ULONG_MAX; struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT; struct stat st; - const char *cmd = "launchctl"; + char *cmd; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); preamble = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">" @@ -1974,6 +2020,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "<array>\n" "<string>%s/git</string>\n" "<string>--exec-path=%s</string>\n" + "%s" /* For extra config parameters. */ "<string>for-each-repo</string>\n" "<string>--keep-going</string>\n" "<string>--config=maintenance.repo</string>\n" @@ -1983,7 +2030,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "</array>\n" "<key>StartCalendarInterval</key>\n" "<array>\n"; - strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency); + strbuf_addf(&plist, preamble, name, exec_path, exec_path, + get_extra_launchctl_strings(), frequency); switch (schedule) { case SCHEDULE_HOURLY: @@ -2054,6 +2102,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit free(filename); free(name); + free(cmd); strbuf_release(&plist); strbuf_release(&plist2); return 0; @@ -2078,9 +2127,8 @@ static int launchctl_update_schedule(int run_maintenance, int fd UNUSED) static int is_schtasks_available(void) { - const char *cmd = "schtasks"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("schtasks", &is_available, NULL)) return is_available; #ifdef GIT_WINDOWS_NATIVE @@ -2099,15 +2147,16 @@ static char *schtasks_task_name(const char *frequency) static int schtasks_remove_task(enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); char *name = schtasks_task_name(frequency); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/delete", "/tn", name, "/f", NULL); free(name); + free(cmd); return run_command(&child); } @@ -2121,7 +2170,7 @@ static int schtasks_remove_tasks(void) static int schtasks_schedule_task(const char *exec_path, enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; const char *xml; @@ -2131,7 +2180,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority struct strbuf tfilename = STRBUF_INIT; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strbuf_addf(&tfilename, "%s/schedule_%s_XXXXXX", repo_get_common_dir(the_repository), frequency); @@ -2218,11 +2267,12 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "<Actions Context=\"Author\">\n" "<Exec>\n" "<Command>\"%s\\headless-git.exe\"</Command>\n" - "<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" + "<Arguments>--exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" "</Exec>\n" "</Actions>\n" "</Task>\n"; - fprintf(tfile->fp, xml, exec_path, exec_path, frequency); + fprintf(tfile->fp, xml, exec_path, exec_path, + get_extra_config_parameters(), frequency); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml", get_tempfile_path(tfile), NULL); @@ -2237,6 +2287,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority delete_tempfile(&tfile); free(name); + free(cmd); return result; } @@ -2278,21 +2329,28 @@ static int check_crontab_process(const char *cmd) static int is_crontab_available(void) { - const char *cmd = "crontab"; + char *cmd; int is_available; + int ret; - if (get_schedule_cmd(&cmd, &is_available)) - return is_available; + if (get_schedule_cmd("crontab", &is_available, &cmd)) { + ret = is_available; + goto out; + } #ifdef __APPLE__ /* * macOS has cron, but it requires special permissions and will * create a UI alert when attempting to run this command. */ - return 0; + ret = 0; #else - return check_crontab_process(cmd); + ret = check_crontab_process(cmd); #endif + +out: + free(cmd); + return ret; } #define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE" @@ -2300,7 +2358,7 @@ static int is_crontab_available(void) static int crontab_update_schedule(int run_maintenance, int fd) { - const char *cmd = "crontab"; + char *cmd; int result = 0; int in_old_region = 0; struct child_process crontab_list = CHILD_PROCESS_INIT; @@ -2310,15 +2368,17 @@ static int crontab_update_schedule(int run_maintenance, int fd) struct tempfile *tmpedit = NULL; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("crontab", NULL, &cmd); strvec_split(&crontab_list.args, cmd); strvec_push(&crontab_list.args, "-l"); crontab_list.in = -1; crontab_list.out = dup(fd); crontab_list.git_cmd = 0; - if (start_command(&crontab_list)) - return error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + if (start_command(&crontab_list)) { + result = error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + goto out; + } /* Ignore exit code, as an empty crontab will return error. */ finish_command(&crontab_list); @@ -2363,8 +2423,8 @@ static int crontab_update_schedule(int run_maintenance, int fd) "# replaced in the future by a Git command.\n\n"); strbuf_addf(&line_format, - "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", - exec_path, exec_path); + "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", + exec_path, exec_path, get_extra_config_parameters()); fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly"); fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily"); fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly"); @@ -2388,8 +2448,10 @@ static int crontab_update_schedule(int run_maintenance, int fd) result = error(_("'crontab' died")); else fclose(cron_list); + out: delete_tempfile(&tmpedit); + free(cmd); return result; } @@ -2412,10 +2474,9 @@ static int real_is_systemd_timer_available(void) static int is_systemd_timer_available(void) { - const char *cmd = "systemctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("systemctl", &is_available, NULL)) return is_available; return real_is_systemd_timer_available(); @@ -2564,7 +2625,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "\n" "[Service]\n" "Type=oneshot\n" - "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" + "ExecStart=\"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" "LockPersonality=yes\n" "MemoryDenyWriteExecute=yes\n" "NoNewPrivileges=yes\n" @@ -2574,7 +2635,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "RestrictSUIDSGID=yes\n" "SystemCallArchitectures=native\n" "SystemCallFilter=@system-service\n"; - if (fprintf(file, unit, exec_path, exec_path) < 0) { + if (fprintf(file, unit, exec_path, exec_path, get_extra_config_parameters()) < 0) { error(_("failed to write to '%s'"), filename); fclose(file); goto error; @@ -2596,9 +2657,10 @@ static int systemd_timer_enable_unit(int enable, enum schedule_priority schedule, int minute) { - const char *cmd = "systemctl"; + char *cmd = NULL; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); + int ret; /* * Disabling the systemd unit while it is already disabled makes @@ -2609,20 +2671,25 @@ static int systemd_timer_enable_unit(int enable, * On the other hand, enabling a systemd unit which is already enabled * produces no error. */ - if (!enable) + if (!enable) { child.no_stderr = 1; - else if (systemd_timer_write_timer_file(schedule, minute)) - return -1; + } else if (systemd_timer_write_timer_file(schedule, minute)) { + ret = -1; + goto out; + } - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("systemctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "--user", enable ? "enable" : "disable", "--now", NULL); strvec_pushf(&child.args, SYSTEMD_UNIT_FORMAT, frequency, "timer"); - if (start_command(&child)) - return error(_("failed to start systemctl")); - if (finish_command(&child)) + if (start_command(&child)) { + ret = error(_("failed to start systemctl")); + goto out; + } + + if (finish_command(&child)) { /* * Disabling an already disabled systemd unit makes * systemctl fail. @@ -2630,9 +2697,17 @@ static int systemd_timer_enable_unit(int enable, * * Enabling an enabled systemd unit doesn't fail. */ - if (enable) - return error(_("failed to run systemctl")); - return 0; + if (enable) { + ret = error(_("failed to run systemctl")); + goto out; + } + } + + ret = 0; + +out: + free(cmd); + return ret; } /* diff --git a/builtin/help.c b/builtin/help.c index a509241a80..4a5a079070 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -54,7 +54,7 @@ static enum help_action { HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION, } cmd_mode; -static const char *html_path; +static char *html_path; static int verbose = 1; static enum help_format help_format = HELP_FORMAT_NONE; static int exclude_guides; @@ -411,6 +411,7 @@ static int git_help_config(const char *var, const char *value, if (!strcmp(var, "help.htmlpath")) { if (!value) return config_error_nonbool(var); + free(html_path); html_path = xstrdup(value); return 0; } @@ -515,23 +516,24 @@ static void show_info_page(const char *page) static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; + const char *path = html_path; char *to_free = NULL; - if (!html_path) - html_path = to_free = system_path(GIT_HTML_PATH); + if (!path) + path = to_free = system_path(GIT_HTML_PATH); /* * Check that the page we're looking for exists. */ - if (!strstr(html_path, "://")) { - if (stat(mkpath("%s/%s.html", html_path, page), &st) + if (!strstr(path, "://")) { + if (stat(mkpath("%s/%s.html", path, page), &st) || !S_ISREG(st.st_mode)) die("'%s/%s.html': documentation file not found.", - html_path, page); + path, page); } strbuf_init(page_path, 0); - strbuf_addf(page_path, "%s/%s.html", html_path, page); + strbuf_addf(page_path, "%s/%s.html", path, page); free(to_free); } diff --git a/builtin/index-pack.c b/builtin/index-pack.c index e228c56ff2..9d23b41b3a 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name, struct strbuf *name, unsigned char *hash, const char *ext, int make_read_only_if_same) { - if (*final_name != curr_name) { + if (!*final_name || strcmp(*final_name, curr_name)) { if (!*final_name) *final_name = odb_pack_name(name, hash, ext); if (finalize_object_file(curr_name, *final_name)) @@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc, { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; const char *curr_index; - const char *curr_rev_index = NULL; + char *curr_rev_index = NULL; const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; const char *keep_msg = NULL; const char *promisor_msg = NULL; @@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc, free((void *) curr_pack); if (!index_name) free((void *) curr_index); - if (!rev_index_name) - free((void *) curr_rev_index); + free(curr_rev_index); /* * Let the caller know this pack is not self contained diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index f723b3bf3b..423318f87e 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -173,5 +173,6 @@ int cmd_ls_remote(int argc, transport_ls_refs_options_release(&transport_options); strvec_clear(&pattern); + string_list_clear(&server_options, 0); return status; } diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 81f4494d46..5809613002 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -69,6 +69,15 @@ static inline void llist_init(struct llist **list) (*list)->size = 0; } +static void llist_free(struct llist *list) +{ + for (struct llist_item *i = list->front, *next; i; i = next) { + next = i->next; + llist_item_put(i); + } + free(list); +} + static struct llist * llist_copy(struct llist *list) { struct llist *ret; @@ -206,6 +215,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl, return p; } +static void pack_list_free(struct pack_list *pl) +{ + for (struct pack_list *next; pl; pl = next) { + next = pl->next; + free(pl); + } +} + static inline size_t pack_list_size(struct pack_list *pl) { size_t ret = 0; @@ -419,7 +436,8 @@ static void minimize(struct pack_list **min) /* return if there are no objects missing from the unique set */ if (missing->size == 0) { - free(missing); + llist_free(missing); + pack_list_free(non_unique); return; } @@ -434,6 +452,8 @@ static void minimize(struct pack_list **min) } while (non_unique) { + struct pack_list *next; + /* sort the non_unique packs, greater size of remaining_objects first */ sort_pack_list(&non_unique); if (non_unique->remaining_objects->size == 0) @@ -444,8 +464,14 @@ static void minimize(struct pack_list **min) for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next) llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects); - non_unique = non_unique->next; + next = non_unique->next; + free(non_unique); + non_unique = next; } + + pack_list_free(non_unique); + llist_free(unique_pack_objects); + llist_free(missing); } static void load_all_objects(void) @@ -565,7 +591,6 @@ static void load_all(void) int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl; struct llist *ignore; - struct object_id *oid; char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ if (argc == 2 && !strcmp(argv[1], "-h")) @@ -625,11 +650,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s /* ignore objects given on stdin */ llist_init(&ignore); if (!isatty(0)) { + struct object_id oid; while (fgets(buf, sizeof(buf), stdin)) { - oid = xmalloc(sizeof(*oid)); - if (get_oid_hex(buf, oid)) + if (get_oid_hex(buf, &oid)) die("Bad object ID on stdin: %s", buf); - llist_insert_sorted_unique(ignore, oid, NULL); + llist_insert_sorted_unique(ignore, &oid, NULL); } } llist_sorted_difference_inplace(all_objects, ignore); @@ -671,5 +696,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s fprintf(stderr, "%luMB of redundant packs in total.\n", (unsigned long)pack_set_bytecount(red)/(1024*1024)); + pack_list_free(red); + pack_list_free(min); + llist_free(ignore); return 0; } diff --git a/builtin/pull.c b/builtin/pull.c index 149f201320..388ef3d130 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -85,7 +85,7 @@ static const char *opt_squash; static const char *opt_commit; static const char *opt_edit; static const char *cleanup_arg; -static const char *opt_ff; +static char *opt_ff; static const char *opt_verify_signatures; static const char *opt_verify; static int opt_autostash = -1; @@ -1028,8 +1028,10 @@ int cmd_pull(int argc, * "--rebase" can override a config setting of * pull.ff=only. */ - if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) - opt_ff = "--ff"; + if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) { + free(opt_ff); + opt_ff = xstrdup("--ff"); + } } if (opt_rebase < 0) @@ -1139,7 +1141,8 @@ int cmd_pull(int argc, if (can_ff) { /* we can fast-forward this without invoking rebase */ - opt_ff = "--ff-only"; + free(opt_ff); + opt_ff = xstrdup("--ff-only"); ret = run_merge(); } else { ret = run_rebase(&newbase, &upstream); diff --git a/builtin/push.c b/builtin/push.c index e6f48969b8..51c609f208 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -519,14 +519,7 @@ static int git_push_config(const char *k, const char *v, RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF; recurse_submodules = val; } else if (!strcmp(k, "push.pushoption")) { - if (!v) - return config_error_nonbool(k); - else - if (!*v) - string_list_clear(&push_options_config, 0); - else - string_list_append(&push_options_config, v); - return 0; + return parse_transport_option(k, v, &push_options_config); } else if (!strcmp(k, "color.push")) { push_use_color = git_config_colorbool(k, v); return 0; @@ -669,6 +662,7 @@ int cmd_push(int argc, rc = do_push(flags, push_options, remote); string_list_clear(&push_options_cmdline, 0); string_list_clear(&push_options_config, 0); + clear_cas_option(&cas); if (rc == -1) usage_with_options(push_usage, options); else diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 536d22761d..ab5b20e39c 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -374,6 +374,7 @@ static void write_head_info(void) struct command { struct command *next; const char *error_string; + char *error_string_owned; struct ref_push_report *report; unsigned int skip_update:1, did_not_exist:1, @@ -1083,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader, hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED; if (!strcmp(head, "ng")) { if (p) - hint->error_string = xstrdup(p); + hint->error_string = hint->error_string_owned = xstrdup(p); else hint->error_string = "failed"; code = -1; @@ -2054,6 +2055,8 @@ static void free_commands(struct command *commands) while (commands) { struct command *next = commands->next; + ref_push_report_free(commands->report); + free(commands->error_string_owned); free(commands); commands = next; } diff --git a/builtin/repack.c b/builtin/repack.c index cb4420f085..d6bb37e84a 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -86,17 +86,34 @@ static int repack_config(const char *var, const char *value, run_update_server_info = git_config_bool(var, value); return 0; } - if (!strcmp(var, "repack.cruftwindow")) + if (!strcmp(var, "repack.cruftwindow")) { + free(cruft_po_args->window); return git_config_string(&cruft_po_args->window, var, value); - if (!strcmp(var, "repack.cruftwindowmemory")) + } + if (!strcmp(var, "repack.cruftwindowmemory")) { + free(cruft_po_args->window_memory); return git_config_string(&cruft_po_args->window_memory, var, value); - if (!strcmp(var, "repack.cruftdepth")) + } + if (!strcmp(var, "repack.cruftdepth")) { + free(cruft_po_args->depth); return git_config_string(&cruft_po_args->depth, var, value); - if (!strcmp(var, "repack.cruftthreads")) + } + if (!strcmp(var, "repack.cruftthreads")) { + free(cruft_po_args->threads); return git_config_string(&cruft_po_args->threads, var, value); + } return git_default_config(var, value, ctx, cb); } +static void pack_objects_args_release(struct pack_objects_args *args) +{ + free(args->window); + free(args->window_memory); + free(args->depth); + free(args->threads); + list_objects_filter_release(&args->filter_options); +} + struct existing_packs { struct string_list kept_packs; struct string_list non_kept_packs; @@ -1156,12 +1173,16 @@ int cmd_repack(int argc, const char *unpack_unreachable = NULL; int keep_unreachable = 0; struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; - struct pack_objects_args po_args = {NULL}; - struct pack_objects_args cruft_po_args = {NULL}; + struct pack_objects_args po_args = { 0 }; + struct pack_objects_args cruft_po_args = { 0 }; int write_midx = 0; const char *cruft_expiration = NULL; const char *expire_to = NULL; const char *filter_to = NULL; + const char *opt_window = NULL; + const char *opt_window_memory = NULL; + const char *opt_depth = NULL; + const char *opt_threads = NULL; struct option builtin_repack_options[] = { OPT_BIT('a', NULL, &pack_everything, @@ -1195,13 +1216,13 @@ int cmd_repack(int argc, N_("with -A, do not loosen objects older than this")), OPT_BOOL('k', "keep-unreachable", &keep_unreachable, N_("with -a, repack unreachable objects")), - OPT_STRING(0, "window", &po_args.window, N_("n"), + OPT_STRING(0, "window", &opt_window, N_("n"), N_("size of the window used for delta compression")), - OPT_STRING(0, "window-memory", &po_args.window_memory, N_("bytes"), + OPT_STRING(0, "window-memory", &opt_window_memory, N_("bytes"), N_("same as the above, but limit memory size instead of entries count")), - OPT_STRING(0, "depth", &po_args.depth, N_("n"), + OPT_STRING(0, "depth", &opt_depth, N_("n"), N_("limits the maximum delta depth")), - OPT_STRING(0, "threads", &po_args.threads, N_("n"), + OPT_STRING(0, "threads", &opt_threads, N_("n"), N_("limits the maximum number of threads")), OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size, N_("maximum size of each packfile")), @@ -1228,6 +1249,11 @@ int cmd_repack(int argc, argc = parse_options(argc, argv, prefix, builtin_repack_options, git_repack_usage, 0); + po_args.window = xstrdup_or_null(opt_window); + po_args.window_memory = xstrdup_or_null(opt_window_memory); + po_args.depth = xstrdup_or_null(opt_depth); + po_args.threads = xstrdup_or_null(opt_threads); + if (delete_redundant && repository_format_precious_objects) die(_("cannot delete packs in a precious-objects repo")); @@ -1393,13 +1419,13 @@ int cmd_repack(int argc, const char *pack_prefix = find_pack_prefix(packdir, packtmp); if (!cruft_po_args.window) - cruft_po_args.window = po_args.window; + cruft_po_args.window = xstrdup_or_null(po_args.window); if (!cruft_po_args.window_memory) - cruft_po_args.window_memory = po_args.window_memory; + cruft_po_args.window_memory = xstrdup_or_null(po_args.window_memory); if (!cruft_po_args.depth) - cruft_po_args.depth = po_args.depth; + cruft_po_args.depth = xstrdup_or_null(po_args.depth); if (!cruft_po_args.threads) - cruft_po_args.threads = po_args.threads; + cruft_po_args.threads = xstrdup_or_null(po_args.threads); if (!cruft_po_args.max_pack_size) cruft_po_args.max_pack_size = po_args.max_pack_size; @@ -1552,7 +1578,8 @@ cleanup: string_list_clear(&names, 1); existing_packs_release(&existing); free_pack_geometry(&geometry); - list_objects_filter_release(&po_args.filter_options); + pack_objects_args_release(&po_args); + pack_objects_args_release(&cruft_po_args); return ret; } diff --git a/builtin/revert.c b/builtin/revert.c index 55ba1092c5..b7917dddd3 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char *me = action_name(opts); const char *cleanup_arg = NULL; + const char sentinel_value; + const char *strategy = &sentinel_value; + const char *gpg_sign = &sentinel_value; enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; int cmd = 0; struct option base_options[] = { @@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, OPT_CALLBACK('m', "mainline", opts, N_("parent-number"), N_("select mainline parent"), option_parse_m), OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto), - OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")), + OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"), N_("option for merge strategy")), - { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), + { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_END() }; @@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, usage_with_options(usage_str, options); /* These option values will be free()d */ - opts->gpg_sign = xstrdup_or_null(opts->gpg_sign); - opts->strategy = xstrdup_or_null(opts->strategy); + if (gpg_sign != &sentinel_value) { + free(opts->gpg_sign); + opts->gpg_sign = xstrdup_or_null(gpg_sign); + } + if (strategy != &sentinel_value) { + free(opts->strategy); + opts->strategy = xstrdup_or_null(strategy); + } if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); free(options); diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 81fc96d423..59b626aae8 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -340,8 +340,11 @@ int cmd_send_pack(int argc, /* stable plumbing output; do not modify or localize */ fprintf(stderr, "Everything up-to-date\n"); + string_list_clear(&push_options, 0); free_refs(remote_refs); free_refs(local_refs); refspec_clear(&rs); + oid_array_clear(&shallow); + clear_cas_option(&cas); return ret; } diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index e4e791a4c9..49aedc1de8 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -924,6 +924,11 @@ static int sparse_checkout_disable(int argc, const char **argv, builtin_sparse_checkout_disable_options, builtin_sparse_checkout_disable_usage, 0); + /* + * Disable the advice message for expanding a sparse index, as we + * are expecting to do that when disabling sparse-checkout. + */ + give_advice_on_expansion = 0; repo_read_index(the_repository); memset(&pl, 0, sizeof(pl)); diff --git a/builtin/stash.c b/builtin/stash.c index f1acc918d0..1399a1bbe2 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1759,7 +1759,7 @@ static int push_stash(int argc, const char **argv, const char *prefix, int quiet = 0; int pathspec_file_nul = 0; const char *stash_msg = NULL; - const char *pathspec_from_file = NULL; + char *pathspec_from_file = NULL; struct pathspec ps; struct option options[] = { OPT_BOOL('k', "keep-index", &keep_index, @@ -1821,7 +1821,9 @@ static int push_stash(int argc, const char **argv, const char *prefix, ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, include_untracked, only_staged); + clear_pathspec(&ps); + free(pathspec_from_file); return ret; } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index a1ada86952..b6b5f1ebde 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -364,9 +364,13 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, if (!info->quiet) printf(_("Entering '%s'\n"), displaypath); - if (info->argv[0] && run_command(&cp)) - die(_("run_command returned non-zero status for %s\n."), - displaypath); + if (info->argv[0]) { + if (run_command(&cp)) + die(_("run_command returned non-zero status for %s\n."), + displaypath); + } else { + child_process_clear(&cp); + } if (info->recursive) { struct child_process cpr = CHILD_PROCESS_INIT; @@ -696,6 +700,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_RECURSIVE) { struct child_process cpr = CHILD_PROCESS_INIT; + int res; cpr.git_cmd = 1; cpr.dir = path; @@ -711,7 +716,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_QUIET) strvec_push(&cpr.args, "--quiet"); - if (run_command(&cpr)) + res = run_command(&cpr); + if (res == SIGPIPE + 128) + raise(SIGPIPE); + else if (res) die(_("failed to recurse into submodule '%s'"), path); } @@ -1618,6 +1626,8 @@ static int add_possible_reference_from_superproject( ; /* nothing */ } } + + strbuf_release(&err); strbuf_release(&sb); } @@ -2022,6 +2032,7 @@ struct update_data { static void update_data_release(struct update_data *ud) { free(ud->displaypath); + submodule_update_strategy_release(&ud->update_strategy); module_list_release(&ud->list); } @@ -2322,7 +2333,14 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, strvec_pushf(&cp.args, "--depth=%d", depth); if (oid) { char *hex = oid_to_hex(oid); - char *remote = get_default_remote(); + char *remote; + int code; + + code = get_default_remote_submodule(module_path, &remote); + if (code) { + child_process_clear(&cp); + return code; + } strvec_pushl(&cp.args, remote, hex, NULL); free(remote); @@ -2642,15 +2660,20 @@ static int update_submodule(struct update_data *update_data) if (!update_data->nofetch) { if (fetch_in_submodule(update_data->sm_path, update_data->depth, - 0, NULL)) + 0, NULL)) { + free(remote_ref); return die_message(_("Unable to fetch in submodule path '%s'"), update_data->sm_path); + } } if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, - remote_ref, &update_data->oid)) - return die_message(_("Unable to find %s revision in submodule path '%s'"), - remote_ref, update_data->sm_path); + remote_ref, &update_data->oid)) { + ret = die_message(_("Unable to find %s revision in submodule path '%s'"), + remote_ref, update_data->sm_path); + free(remote_ref); + return ret; + } free(remote_ref); } diff --git a/builtin/worktree.c b/builtin/worktree.c index fc31d072a6..dae63dedf4 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -414,7 +414,8 @@ static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; - struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT, sb_tmp = STRBUF_INIT; + struct strbuf sb_path_realpath = STRBUF_INIT, sb_repo_realpath = STRBUF_INIT; const char *name; struct strvec child_env = STRVEC_INIT; unsigned int counter = 0; @@ -490,11 +491,10 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - strbuf_realpath(&realpath, sb_git.buf, 1); - write_file(sb.buf, "%s", realpath.buf); - strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1); - write_file(sb_git.buf, "gitdir: %s/worktrees/%s", - realpath.buf, name); + strbuf_realpath(&sb_path_realpath, path, 1); + strbuf_realpath(&sb_repo_realpath, sb_repo.buf, 1); + write_file(sb.buf, "%s/.git", relative_path(sb_path_realpath.buf, sb_repo_realpath.buf, &sb_tmp)); + write_file(sb_git.buf, "gitdir: %s", relative_path(sb_repo_realpath.buf, sb_path_realpath.buf, &sb_tmp)); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -578,11 +578,13 @@ done: strvec_clear(&child_env); strbuf_release(&sb); + strbuf_release(&sb_tmp); strbuf_release(&symref); strbuf_release(&sb_repo); + strbuf_release(&sb_repo_realpath); strbuf_release(&sb_git); + strbuf_release(&sb_path_realpath); strbuf_release(&sb_name); - strbuf_release(&realpath); free_worktree(wt); return ret; } |
