1
0
mirror of https://github.com/git/git synced 2024-06-30 22:54:27 +00:00

Merge branch 'ps/leakfixes'

Leakfixes.

* ps/leakfixes:
  builtin/mv: fix leaks for submodule gitfile paths
  builtin/mv: refactor to use `struct strvec`
  builtin/mv duplicate string list memory
  builtin/mv: refactor `add_slash()` to always return allocated strings
  strvec: add functions to replace and remove strings
  submodule: fix leaking memory for submodule entries
  commit-reach: fix memory leak in `ahead_behind()`
  builtin/credential: clear credential before exit
  config: plug various memory leaks
  config: clarify memory ownership in `git_config_string()`
  builtin/log: stop using globals for format config
  builtin/log: stop using globals for log config
  convert: refactor code to clarify ownership of check_roundtrip_encoding
  diff: refactor code to clarify memory ownership of prefixes
  config: clarify memory ownership in `git_config_pathname()`
  http: refactor code to clarify memory ownership
  checkout: clarify memory ownership in `unique_tracking_name()`
  strbuf: fix leak when `appendwholeline()` fails with EOF
  transport-helper: fix leaking helper name
This commit is contained in:
Junio C Hamano 2024-06-06 12:49:23 -07:00
commit cf792653ad
97 changed files with 1141 additions and 588 deletions

View File

@ -1338,6 +1338,7 @@ UNIT_TEST_PROGRAMS += t-mem-pool
UNIT_TEST_PROGRAMS += t-prio-queue UNIT_TEST_PROGRAMS += t-prio-queue
UNIT_TEST_PROGRAMS += t-strbuf UNIT_TEST_PROGRAMS += t-strbuf
UNIT_TEST_PROGRAMS += t-strcmp-offset UNIT_TEST_PROGRAMS += t-strcmp-offset
UNIT_TEST_PROGRAMS += t-strvec
UNIT_TEST_PROGRAMS += t-trailer UNIT_TEST_PROGRAMS += t-trailer
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))

View File

@ -21,9 +21,11 @@ static int config_alias_cb(const char *key, const char *value,
return 0; return 0;
if (data->alias) { if (data->alias) {
if (!strcasecmp(p, data->alias)) if (!strcasecmp(p, data->alias)) {
return git_config_string((const char **)&data->v, FREE_AND_NULL(data->v);
return git_config_string(&data->v,
key, value); key, value);
}
} else if (data->list) { } else if (data->list) {
string_list_append(data->list, p); string_list_append(data->list, p);
} }

2
attr.c
View File

@ -25,7 +25,7 @@
#include "tree-walk.h" #include "tree-walk.h"
#include "object-name.h" #include "object-name.h"
const char *git_attr_tree; char *git_attr_tree;
const char git_attr__true[] = "(builtin)true"; const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false"; const char git_attr__false[] = "\0(builtin)false";

2
attr.h
View File

@ -236,6 +236,6 @@ const char *git_attr_global_file(void);
/* Return whether the system gitattributes file is enabled and should be used. */ /* Return whether the system gitattributes file is enabled and should be used. */
int git_attr_system_is_enabled(void); int git_attr_system_is_enabled(void);
extern const char *git_attr_tree; extern char *git_attr_tree;
#endif /* ATTR_H */ #endif /* ATTR_H */

View File

@ -718,7 +718,7 @@ static int git_blame_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "blame.ignorerevsfile")) { if (!strcmp(var, "blame.ignorerevsfile")) {
const char *str; char *str;
int ret; int ret;
ret = git_config_pathname(&str, var, value); ret = git_config_pathname(&str, var, value);

View File

@ -1275,12 +1275,12 @@ static void setup_new_branch_info_and_source_tree(
} }
} }
static const char *parse_remote_branch(const char *arg, static char *parse_remote_branch(const char *arg,
struct object_id *rev, struct object_id *rev,
int could_be_checkout_paths) int could_be_checkout_paths)
{ {
int num_matches = 0; int num_matches = 0;
const char *remote = unique_tracking_name(arg, rev, &num_matches); char *remote = unique_tracking_name(arg, rev, &num_matches);
if (remote && could_be_checkout_paths) { if (remote && could_be_checkout_paths) {
die(_("'%s' could be both a local file and a tracking branch.\n" die(_("'%s' could be both a local file and a tracking branch.\n"
@ -1316,6 +1316,7 @@ static int parse_branchname_arg(int argc, const char **argv,
const char **new_branch = &opts->new_branch; const char **new_branch = &opts->new_branch;
int argcount = 0; int argcount = 0;
const char *arg; const char *arg;
char *remote = NULL;
int dash_dash_pos; int dash_dash_pos;
int has_dash_dash = 0; int has_dash_dash = 0;
int i; int i;
@ -1416,8 +1417,8 @@ static int parse_branchname_arg(int argc, const char **argv,
recover_with_dwim = 0; recover_with_dwim = 0;
if (recover_with_dwim) { if (recover_with_dwim) {
const char *remote = parse_remote_branch(arg, rev, remote = parse_remote_branch(arg, rev,
could_be_checkout_paths); could_be_checkout_paths);
if (remote) { if (remote) {
*new_branch = arg; *new_branch = arg;
arg = remote; arg = remote;
@ -1459,6 +1460,7 @@ static int parse_branchname_arg(int argc, const char **argv,
argc--; argc--;
} }
free(remote);
return argcount; return argcount;
} }

View File

@ -107,7 +107,7 @@ static enum {
} commit_style; } commit_style;
static const char *logfile, *force_author; static const char *logfile, *force_author;
static const char *template_file; static char *template_file;
/* /*
* The _message variables are commit names from which to take * The _message variables are commit names from which to take
* the commit message and/or authorship. * the commit message and/or authorship.
@ -133,7 +133,7 @@ static struct strvec trailer_args = STRVEC_INIT;
* is specified explicitly. * is specified explicitly.
*/ */
static enum commit_msg_cleanup_mode cleanup_mode; static enum commit_msg_cleanup_mode cleanup_mode;
static const char *cleanup_arg; static char *cleanup_arg;
static enum commit_whence whence; static enum commit_whence whence;
static int use_editor = 1, include_status = 1; static int use_editor = 1, include_status = 1;

View File

@ -289,7 +289,7 @@ static int format_config(const struct config_display_options *opts,
else else
strbuf_addstr(buf, v ? "true" : "false"); strbuf_addstr(buf, v ? "true" : "false");
} else if (opts->type == TYPE_PATH) { } else if (opts->type == TYPE_PATH) {
const char *v; char *v;
if (git_config_pathname(&v, key_, value_) < 0) if (git_config_pathname(&v, key_, value_) < 0)
return -1; return -1;
strbuf_addstr(buf, v); strbuf_addstr(buf, v);

View File

@ -39,5 +39,7 @@ int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
} else { } else {
usage(usage_msg); usage(usage_msg);
} }
credential_clear(&c);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -100,7 +100,7 @@ static struct strategy all_strategy[] = {
{ "subtree", NO_FAST_FORWARD | NO_TRIVIAL }, { "subtree", NO_FAST_FORWARD | NO_TRIVIAL },
}; };
static const char *pull_twohead, *pull_octopus; static char *pull_twohead, *pull_octopus;
enum ff_type { enum ff_type {
FF_NO, FF_NO,
@ -110,7 +110,7 @@ enum ff_type {
static enum ff_type fast_forward = FF_ALLOW; static enum ff_type fast_forward = FF_ALLOW;
static const char *cleanup_arg; static char *cleanup_arg;
static enum commit_msg_cleanup_mode cleanup_mode; static enum commit_msg_cleanup_mode cleanup_mode;
static int option_parse_message(const struct option *opt, static int option_parse_message(const struct option *opt,

View File

@ -20,6 +20,7 @@
#include "read-cache-ll.h" #include "read-cache-ll.h"
#include "repository.h" #include "repository.h"
#include "setup.h" #include "setup.h"
#include "strvec.h"
#include "submodule.h" #include "submodule.h"
#include "entry.h" #include "entry.h"
@ -38,45 +39,35 @@ enum update_mode {
#define DUP_BASENAME 1 #define DUP_BASENAME 1
#define KEEP_TRAILING_SLASH 2 #define KEEP_TRAILING_SLASH 2
static const char **internal_prefix_pathspec(const char *prefix, static void internal_prefix_pathspec(struct strvec *out,
const char **pathspec, const char *prefix,
int count, unsigned flags) const char **pathspec,
int count, unsigned flags)
{ {
int i;
const char **result;
int prefixlen = prefix ? strlen(prefix) : 0; int prefixlen = prefix ? strlen(prefix) : 0;
ALLOC_ARRAY(result, count + 1);
/* Create an intermediate copy of the pathspec based on the flags */ /* Create an intermediate copy of the pathspec based on the flags */
for (i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
int length = strlen(pathspec[i]); size_t length = strlen(pathspec[i]);
int to_copy = length; size_t to_copy = length;
char *it; const char *maybe_basename;
char *trimmed, *prefixed_path;
while (!(flags & KEEP_TRAILING_SLASH) && while (!(flags & KEEP_TRAILING_SLASH) &&
to_copy > 0 && is_dir_sep(pathspec[i][to_copy - 1])) to_copy > 0 && is_dir_sep(pathspec[i][to_copy - 1]))
to_copy--; to_copy--;
it = xmemdupz(pathspec[i], to_copy); trimmed = xmemdupz(pathspec[i], to_copy);
if (flags & DUP_BASENAME) { maybe_basename = (flags & DUP_BASENAME) ? basename(trimmed) : trimmed;
result[i] = xstrdup(basename(it)); prefixed_path = prefix_path(prefix, prefixlen, maybe_basename);
free(it); strvec_push(out, prefixed_path);
} else {
result[i] = it;
}
}
result[count] = NULL;
/* Prefix the pathspec and free the old intermediate strings */ free(prefixed_path);
for (i = 0; i < count; i++) { free(trimmed);
const char *match = prefix_path(prefix, prefixlen, result[i]);
free((char *) result[i]);
result[i] = match;
} }
return result;
} }
static const char *add_slash(const char *path) static char *add_slash(const char *path)
{ {
size_t len = strlen(path); size_t len = strlen(path);
if (len && path[len - 1] != '/') { if (len && path[len - 1] != '/') {
@ -86,32 +77,34 @@ static const char *add_slash(const char *path)
with_slash[len] = 0; with_slash[len] = 0;
return with_slash; return with_slash;
} }
return path; return xstrdup(path);
} }
#define SUBMODULE_WITH_GITDIR ((const char *)1) #define SUBMODULE_WITH_GITDIR ((const char *)1)
static void prepare_move_submodule(const char *src, int first, static const char *submodule_gitfile_path(const char *src, int first)
const char **submodule_gitfile)
{ {
struct strbuf submodule_dotgit = STRBUF_INIT; struct strbuf submodule_dotgit = STRBUF_INIT;
const char *path;
if (!S_ISGITLINK(the_repository->index->cache[first]->ce_mode)) if (!S_ISGITLINK(the_repository->index->cache[first]->ce_mode))
die(_("Directory %s is in index and no submodule?"), src); die(_("Directory %s is in index and no submodule?"), src);
if (!is_staging_gitmodules_ok(the_repository->index)) if (!is_staging_gitmodules_ok(the_repository->index))
die(_("Please stage your changes to .gitmodules or stash them to proceed")); die(_("Please stage your changes to .gitmodules or stash them to proceed"));
strbuf_addf(&submodule_dotgit, "%s/.git", src); strbuf_addf(&submodule_dotgit, "%s/.git", src);
*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
if (*submodule_gitfile) path = read_gitfile(submodule_dotgit.buf);
*submodule_gitfile = xstrdup(*submodule_gitfile);
else
*submodule_gitfile = SUBMODULE_WITH_GITDIR;
strbuf_release(&submodule_dotgit); strbuf_release(&submodule_dotgit);
if (path)
return path;
return SUBMODULE_WITH_GITDIR;
} }
static int index_range_of_same_dir(const char *src, int length, static int index_range_of_same_dir(const char *src, int length,
int *first_p, int *last_p) int *first_p, int *last_p)
{ {
const char *src_w_slash = add_slash(src); char *src_w_slash = add_slash(src);
int first, last, len_w_slash = length + 1; int first, last, len_w_slash = length + 1;
first = index_name_pos(the_repository->index, src_w_slash, len_w_slash); first = index_name_pos(the_repository->index, src_w_slash, len_w_slash);
@ -124,8 +117,8 @@ static int index_range_of_same_dir(const char *src, int length,
if (strncmp(path, src_w_slash, len_w_slash)) if (strncmp(path, src_w_slash, len_w_slash))
break; break;
} }
if (src_w_slash != src)
free((char *)src_w_slash); free(src_w_slash);
*first_p = first; *first_p = first;
*last_p = last; *last_p = last;
return last - first; return last - first;
@ -141,7 +134,7 @@ static int index_range_of_same_dir(const char *src, int length,
static int empty_dir_has_sparse_contents(const char *name) static int empty_dir_has_sparse_contents(const char *name)
{ {
int ret = 0; int ret = 0;
const char *with_slash = add_slash(name); char *with_slash = add_slash(name);
int length = strlen(with_slash); int length = strlen(with_slash);
int pos = index_name_pos(the_repository->index, with_slash, length); int pos = index_name_pos(the_repository->index, with_slash, length);
@ -159,8 +152,7 @@ static int empty_dir_has_sparse_contents(const char *name)
} }
free_return: free_return:
if (with_slash != name) free(with_slash);
free((char *)with_slash);
return ret; return ret;
} }
@ -177,18 +169,23 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "sparse", &ignore_sparse, N_("allow updating entries outside of the sparse-checkout cone")), OPT_BOOL(0, "sparse", &ignore_sparse, N_("allow updating entries outside of the sparse-checkout cone")),
OPT_END(), OPT_END(),
}; };
const char **source, **destination, **dest_path, **submodule_gitfile; struct strvec sources = STRVEC_INIT;
const char *dst_w_slash; struct strvec dest_paths = STRVEC_INIT;
struct strvec destinations = STRVEC_INIT;
struct strvec submodule_gitfiles_to_free = STRVEC_INIT;
const char **submodule_gitfiles;
char *dst_w_slash = NULL;
const char **src_dir = NULL; const char **src_dir = NULL;
int src_dir_nr = 0, src_dir_alloc = 0; int src_dir_nr = 0, src_dir_alloc = 0;
struct strbuf a_src_dir = STRBUF_INIT; struct strbuf a_src_dir = STRBUF_INIT;
enum update_mode *modes, dst_mode = 0; enum update_mode *modes, dst_mode = 0;
struct stat st, dest_st; struct stat st, dest_st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP; struct string_list src_for_dst = STRING_LIST_INIT_DUP;
struct lock_file lock_file = LOCK_INIT; struct lock_file lock_file = LOCK_INIT;
struct cache_entry *ce; struct cache_entry *ce;
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP; struct string_list only_match_skip_worktree = STRING_LIST_INIT_DUP;
struct string_list dirty_paths = STRING_LIST_INIT_NODUP; struct string_list dirty_paths = STRING_LIST_INIT_DUP;
int ret;
git_config(git_default_config, NULL); git_config(git_default_config, NULL);
@ -201,7 +198,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (repo_read_index(the_repository) < 0) if (repo_read_index(the_repository) < 0)
die(_("index file corrupt")); die(_("index file corrupt"));
source = internal_prefix_pathspec(prefix, argv, argc, 0); internal_prefix_pathspec(&sources, prefix, argv, argc, 0);
CALLOC_ARRAY(modes, argc); CALLOC_ARRAY(modes, argc);
/* /*
@ -212,45 +209,39 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
flags = KEEP_TRAILING_SLASH; flags = KEEP_TRAILING_SLASH;
if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1])) if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1]))
flags = 0; flags = 0;
dest_path = internal_prefix_pathspec(prefix, argv + argc, 1, flags); internal_prefix_pathspec(&dest_paths, prefix, argv + argc, 1, flags);
dst_w_slash = add_slash(dest_path[0]); dst_w_slash = add_slash(dest_paths.v[0]);
submodule_gitfile = xcalloc(argc, sizeof(char *)); submodule_gitfiles = xcalloc(argc, sizeof(char *));
if (dest_path[0][0] == '\0') if (dest_paths.v[0][0] == '\0')
/* special case: "." was normalized to "" */ /* special case: "." was normalized to "" */
destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME); internal_prefix_pathspec(&destinations, dest_paths.v[0], argv, argc, DUP_BASENAME);
else if (!lstat(dest_path[0], &st) && else if (!lstat(dest_paths.v[0], &st) && S_ISDIR(st.st_mode)) {
S_ISDIR(st.st_mode)) { internal_prefix_pathspec(&destinations, dst_w_slash, argv, argc, DUP_BASENAME);
destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME); } else if (!path_in_sparse_checkout(dst_w_slash, the_repository->index) &&
empty_dir_has_sparse_contents(dst_w_slash)) {
internal_prefix_pathspec(&destinations, dst_w_slash, argv, argc, DUP_BASENAME);
dst_mode = SKIP_WORKTREE_DIR;
} else if (argc != 1) {
die(_("destination '%s' is not a directory"), dest_paths.v[0]);
} else { } else {
if (!path_in_sparse_checkout(dst_w_slash, the_repository->index) && strvec_pushv(&destinations, dest_paths.v);
empty_dir_has_sparse_contents(dst_w_slash)) {
destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME); /*
dst_mode = SKIP_WORKTREE_DIR; * <destination> is a file outside of sparse-checkout
} else if (argc != 1) { * cone. Insist on cone mode here for backward
die(_("destination '%s' is not a directory"), dest_path[0]); * compatibility. We don't want dst_mode to be assigned
} else { * for a file when the repo is using no-cone mode (which
destination = dest_path; * is deprecated at this point) sparse-checkout. As
/* * SPARSE here is only considering cone-mode situation.
* <destination> is a file outside of sparse-checkout */
* cone. Insist on cone mode here for backward if (!path_in_cone_mode_sparse_checkout(destinations.v[0], the_repository->index))
* compatibility. We don't want dst_mode to be assigned dst_mode = SPARSE;
* for a file when the repo is using no-cone mode (which
* is deprecated at this point) sparse-checkout. As
* SPARSE here is only considering cone-mode situation.
*/
if (!path_in_cone_mode_sparse_checkout(destination[0], the_repository->index))
dst_mode = SPARSE;
}
}
if (dst_w_slash != dest_path[0]) {
free((char *)dst_w_slash);
dst_w_slash = NULL;
} }
/* Checking */ /* Checking */
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
const char *src = source[i], *dst = destination[i]; const char *src = sources.v[i], *dst = destinations.v[i];
int length; int length;
const char *bad = NULL; const char *bad = NULL;
int skip_sparse = 0; int skip_sparse = 0;
@ -265,12 +256,14 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
pos = index_name_pos(the_repository->index, src, length); pos = index_name_pos(the_repository->index, src, length);
if (pos < 0) { if (pos < 0) {
const char *src_w_slash = add_slash(src); char *src_w_slash = add_slash(src);
if (!path_in_sparse_checkout(src_w_slash, the_repository->index) && if (!path_in_sparse_checkout(src_w_slash, the_repository->index) &&
empty_dir_has_sparse_contents(src)) { empty_dir_has_sparse_contents(src)) {
free(src_w_slash);
modes[i] |= SKIP_WORKTREE_DIR; modes[i] |= SKIP_WORKTREE_DIR;
goto dir_check; goto dir_check;
} }
free(src_w_slash);
/* only error if existence is expected. */ /* only error if existence is expected. */
if (!(modes[i] & SPARSE)) if (!(modes[i] & SPARSE))
bad = _("bad source"); bad = _("bad source");
@ -310,12 +303,16 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
dir_check: dir_check:
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
int j, dst_len, n; char *dst_with_slash;
size_t dst_with_slash_len;
int j, n;
int first = index_name_pos(the_repository->index, src, length), last; int first = index_name_pos(the_repository->index, src, length), last;
if (first >= 0) { if (first >= 0) {
prepare_move_submodule(src, first, const char *path = submodule_gitfile_path(src, first);
submodule_gitfile + i); if (path != SUBMODULE_WITH_GITDIR)
path = strvec_push(&submodule_gitfiles_to_free, path);
submodule_gitfiles[i] = path;
goto act_on_entry; goto act_on_entry;
} else if (index_range_of_same_dir(src, length, } else if (index_range_of_same_dir(src, length,
&first, &last) < 1) { &first, &last) < 1) {
@ -330,24 +327,28 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
src_dir[src_dir_nr++] = src; src_dir[src_dir_nr++] = src;
n = argc + last - first; n = argc + last - first;
REALLOC_ARRAY(source, n);
REALLOC_ARRAY(destination, n);
REALLOC_ARRAY(modes, n); REALLOC_ARRAY(modes, n);
REALLOC_ARRAY(submodule_gitfile, n); REALLOC_ARRAY(submodule_gitfiles, n);
dst = add_slash(dst); dst_with_slash = add_slash(dst);
dst_len = strlen(dst); dst_with_slash_len = strlen(dst_with_slash);
for (j = 0; j < last - first; j++) { for (j = 0; j < last - first; j++) {
const struct cache_entry *ce = the_repository->index->cache[first + j]; const struct cache_entry *ce = the_repository->index->cache[first + j];
const char *path = ce->name; const char *path = ce->name;
source[argc + j] = path; char *prefixed_path = prefix_path(dst_with_slash, dst_with_slash_len, path + length + 1);
destination[argc + j] =
prefix_path(dst, dst_len, path + length + 1); strvec_push(&sources, path);
strvec_push(&destinations, prefixed_path);
memset(modes + argc + j, 0, sizeof(enum update_mode)); memset(modes + argc + j, 0, sizeof(enum update_mode));
modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX; modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX;
submodule_gitfile[argc + j] = NULL; submodule_gitfiles[argc + j] = NULL;
free(prefixed_path);
} }
free(dst_with_slash);
argc += last - first; argc += last - first;
goto act_on_entry; goto act_on_entry;
} }
@ -428,23 +429,25 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
remove_entry: remove_entry:
if (--argc > 0) { if (--argc > 0) {
int n = argc - i; int n = argc - i;
MOVE_ARRAY(source + i, source + i + 1, n); strvec_remove(&sources, i);
MOVE_ARRAY(destination + i, destination + i + 1, n); strvec_remove(&destinations, i);
MOVE_ARRAY(modes + i, modes + i + 1, n); MOVE_ARRAY(modes + i, modes + i + 1, n);
MOVE_ARRAY(submodule_gitfile + i, MOVE_ARRAY(submodule_gitfiles + i,
submodule_gitfile + i + 1, n); submodule_gitfiles + i + 1, n);
i--; i--;
} }
} }
if (only_match_skip_worktree.nr) { if (only_match_skip_worktree.nr) {
advise_on_updating_sparse_paths(&only_match_skip_worktree); advise_on_updating_sparse_paths(&only_match_skip_worktree);
if (!ignore_errors) if (!ignore_errors) {
return 1; ret = 1;
goto out;
}
} }
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
const char *src = source[i], *dst = destination[i]; const char *src = sources.v[i], *dst = destinations.v[i];
enum update_mode mode = modes[i]; enum update_mode mode = modes[i];
int pos; int pos;
int sparse_and_dirty = 0; int sparse_and_dirty = 0;
@ -464,12 +467,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
continue; continue;
die_errno(_("renaming '%s' failed"), src); die_errno(_("renaming '%s' failed"), src);
} }
if (submodule_gitfile[i]) { if (submodule_gitfiles[i]) {
if (!update_path_in_gitmodules(src, dst)) if (!update_path_in_gitmodules(src, dst))
gitmodules_modified = 1; gitmodules_modified = 1;
if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR) if (submodule_gitfiles[i] != SUBMODULE_WITH_GITDIR)
connect_work_tree_and_git_dir(dst, connect_work_tree_and_git_dir(dst,
submodule_gitfile[i], submodule_gitfiles[i],
1); 1);
} }
@ -565,11 +568,18 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
COMMIT_LOCK | SKIP_IF_UNCHANGED)) COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("Unable to write new index file")); die(_("Unable to write new index file"));
ret = 0;
out:
free(dst_w_slash);
string_list_clear(&src_for_dst, 0); string_list_clear(&src_for_dst, 0);
string_list_clear(&dirty_paths, 0); string_list_clear(&dirty_paths, 0);
UNLEAK(source); string_list_clear(&only_match_skip_worktree, 0);
UNLEAK(dest_path); strvec_clear(&sources);
free(submodule_gitfile); strvec_clear(&dest_paths);
strvec_clear(&destinations);
strvec_clear(&submodule_gitfiles_to_free);
free(submodule_gitfiles);
free(modes); free(modes);
return 0; return ret;
} }

View File

@ -83,7 +83,7 @@ static const char *action_names[] = {
struct rebase_options { struct rebase_options {
enum rebase_type type; enum rebase_type type;
enum empty_type empty; enum empty_type empty;
const char *default_backend; char *default_backend;
const char *state_dir; const char *state_dir;
struct commit *upstream; struct commit *upstream;
const char *upstream_name; const char *upstream_name;

View File

@ -88,7 +88,7 @@ static struct strbuf push_cert = STRBUF_INIT;
static struct object_id push_cert_oid; static struct object_id push_cert_oid;
static struct signature_check sigcheck; static struct signature_check sigcheck;
static const char *push_cert_nonce; static const char *push_cert_nonce;
static const char *cert_nonce_seed; static char *cert_nonce_seed;
static struct strvec hidden_refs = STRVEC_INIT; static struct strvec hidden_refs = STRVEC_INIT;
static const char *NONCE_UNSOLICITED = "UNSOLICITED"; static const char *NONCE_UNSOLICITED = "UNSOLICITED";
@ -168,13 +168,13 @@ static int receive_pack_config(const char *var, const char *value,
} }
if (strcmp(var, "receive.fsck.skiplist") == 0) { if (strcmp(var, "receive.fsck.skiplist") == 0) {
const char *path; char *path;
if (git_config_pathname(&path, var, value)) if (git_config_pathname(&path, var, value))
return 1; return 1;
strbuf_addf(&fsck_msg_types, "%cskiplist=%s", strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
fsck_msg_types.len ? ',' : '=', path); fsck_msg_types.len ? ',' : '=', path);
free((char *)path); free(path);
return 0; return 0;
} }

View File

@ -48,10 +48,10 @@ static const char incremental_bitmap_conflict_error[] = N_(
); );
struct pack_objects_args { struct pack_objects_args {
const char *window; char *window;
const char *window_memory; char *window_memory;
const char *depth; char *depth;
const char *threads; char *threads;
unsigned long max_pack_size; unsigned long max_pack_size;
int no_reuse_delta; int no_reuse_delta;
int no_reuse_object; int no_reuse_object;

View File

@ -736,16 +736,14 @@ static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
return 1; return 1;
} }
static const char *dwim_branch(const char *path, const char **new_branch) static char *dwim_branch(const char *path, char **new_branch)
{ {
int n; int n;
int branch_exists; int branch_exists;
const char *s = worktree_basename(path, &n); const char *s = worktree_basename(path, &n);
const char *branchname = xstrndup(s, n); char *branchname = xstrndup(s, n);
struct strbuf ref = STRBUF_INIT; struct strbuf ref = STRBUF_INIT;
UNLEAK(branchname);
branch_exists = !strbuf_check_branch_ref(&ref, branchname) && branch_exists = !strbuf_check_branch_ref(&ref, branchname) &&
refs_ref_exists(get_main_ref_store(the_repository), refs_ref_exists(get_main_ref_store(the_repository),
ref.buf); ref.buf);
@ -756,8 +754,7 @@ static const char *dwim_branch(const char *path, const char **new_branch)
*new_branch = branchname; *new_branch = branchname;
if (guess_remote) { if (guess_remote) {
struct object_id oid; struct object_id oid;
const char *remote = char *remote = unique_tracking_name(*new_branch, &oid, NULL);
unique_tracking_name(*new_branch, &oid, NULL);
return remote; return remote;
} }
return NULL; return NULL;
@ -769,6 +766,8 @@ static int add(int ac, const char **av, const char *prefix)
const char *new_branch_force = NULL; const char *new_branch_force = NULL;
char *path; char *path;
const char *branch; const char *branch;
char *branch_to_free = NULL;
char *new_branch_to_free = NULL;
const char *new_branch = NULL; const char *new_branch = NULL;
const char *opt_track = NULL; const char *opt_track = NULL;
const char *lock_reason = NULL; const char *lock_reason = NULL;
@ -859,16 +858,17 @@ static int add(int ac, const char **av, const char *prefix)
opts.orphan = dwim_orphan(&opts, !!opt_track, 0); opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
} else if (ac < 2) { } else if (ac < 2) {
/* DWIM: Guess branch name from path. */ /* DWIM: Guess branch name from path. */
const char *s = dwim_branch(path, &new_branch); char *s = dwim_branch(path, &new_branch_to_free);
if (s) if (s)
branch = s; branch = branch_to_free = s;
new_branch = new_branch_to_free;
/* DWIM: Infer --orphan when repo has no refs. */ /* DWIM: Infer --orphan when repo has no refs. */
opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1); opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1);
} else if (ac == 2) { } else if (ac == 2) {
struct object_id oid; struct object_id oid;
struct commit *commit; struct commit *commit;
const char *remote; char *remote;
commit = lookup_commit_reference_by_name(branch); commit = lookup_commit_reference_by_name(branch);
if (!commit) { if (!commit) {
@ -923,6 +923,8 @@ static int add(int ac, const char **av, const char *prefix)
ret = add_worktree(path, branch, &opts); ret = add_worktree(path, branch, &opts);
free(path); free(path);
free(branch_to_free);
free(new_branch_to_free);
return ret; return ret;
} }

View File

@ -45,8 +45,8 @@ static int check_tracking_name(struct remote *remote, void *cb_data)
return 0; return 0;
} }
const char *unique_tracking_name(const char *name, struct object_id *oid, char *unique_tracking_name(const char *name, struct object_id *oid,
int *dwim_remotes_matched) int *dwim_remotes_matched)
{ {
struct tracking_name_data cb_data = TRACKING_NAME_DATA_INIT; struct tracking_name_data cb_data = TRACKING_NAME_DATA_INIT;
const char *default_remote = NULL; const char *default_remote = NULL;

View File

@ -8,8 +8,8 @@
* tracking branch. Return the name of the remote if such a branch * tracking branch. Return the name of the remote if such a branch
* exists, NULL otherwise. * exists, NULL otherwise.
*/ */
const char *unique_tracking_name(const char *name, char *unique_tracking_name(const char *name,
struct object_id *oid, struct object_id *oid,
int *dwim_remotes_matched); int *dwim_remotes_matched);
#endif /* CHECKOUT_H */ #endif /* CHECKOUT_H */

View File

@ -1106,6 +1106,10 @@ void ahead_behind(struct repository *r,
/* STALE is used here, PARENT2 is used by insert_no_dup(). */ /* STALE is used here, PARENT2 is used by insert_no_dup(). */
repo_clear_commit_marks(r, PARENT2 | STALE); repo_clear_commit_marks(r, PARENT2 | STALE);
while (prio_queue_peek(&queue)) {
struct commit *c = prio_queue_get(&queue);
free_bit_array(c);
}
clear_bit_arrays(&bit_arrays); clear_bit_arrays(&bit_arrays);
clear_prio_queue(&queue); clear_prio_queue(&queue);
} }

View File

@ -1338,7 +1338,7 @@ int git_config_bool(const char *name, const char *value)
return v; return v;
} }
int git_config_string(const char **dest, const char *var, const char *value) int git_config_string(char **dest, const char *var, const char *value)
{ {
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
@ -1346,7 +1346,7 @@ int git_config_string(const char **dest, const char *var, const char *value)
return 0; return 0;
} }
int git_config_pathname(const char **dest, const char *var, const char *value) int git_config_pathname(char **dest, const char *var, const char *value)
{ {
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
@ -1414,11 +1414,15 @@ static int git_default_core_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "core.attributesfile")) if (!strcmp(var, "core.attributesfile")) {
FREE_AND_NULL(git_attributes_file);
return git_config_pathname(&git_attributes_file, var, value); return git_config_pathname(&git_attributes_file, var, value);
}
if (!strcmp(var, "core.hookspath")) if (!strcmp(var, "core.hookspath")) {
FREE_AND_NULL(git_hooks_path);
return git_config_pathname(&git_hooks_path, var, value); return git_config_pathname(&git_hooks_path, var, value);
}
if (!strcmp(var, "core.bare")) { if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value); is_bare_repository_cfg = git_config_bool(var, value);
@ -1553,8 +1557,10 @@ static int git_default_core_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "core.checkroundtripencoding")) if (!strcmp(var, "core.checkroundtripencoding")) {
FREE_AND_NULL(check_roundtrip_encoding);
return git_config_string(&check_roundtrip_encoding, var, value); return git_config_string(&check_roundtrip_encoding, var, value);
}
if (!strcmp(var, "core.notesref")) { if (!strcmp(var, "core.notesref")) {
if (!value) if (!value)
@ -1563,8 +1569,10 @@ static int git_default_core_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "core.editor")) if (!strcmp(var, "core.editor")) {
FREE_AND_NULL(editor_program);
return git_config_string(&editor_program, var, value); return git_config_string(&editor_program, var, value);
}
if (!strcmp(var, "core.commentchar") || if (!strcmp(var, "core.commentchar") ||
!strcmp(var, "core.commentstring")) { !strcmp(var, "core.commentstring")) {
@ -1582,11 +1590,13 @@ static int git_default_core_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "core.askpass")) if (!strcmp(var, "core.askpass")) {
FREE_AND_NULL(askpass_program);
return git_config_string(&askpass_program, var, value); return git_config_string(&askpass_program, var, value);
}
if (!strcmp(var, "core.excludesfile")) { if (!strcmp(var, "core.excludesfile")) {
free((char *)excludes_file); FREE_AND_NULL(excludes_file);
return git_config_pathname(&excludes_file, var, value); return git_config_pathname(&excludes_file, var, value);
} }
@ -1689,11 +1699,15 @@ static int git_default_sparse_config(const char *var, const char *value)
static int git_default_i18n_config(const char *var, const char *value) static int git_default_i18n_config(const char *var, const char *value)
{ {
if (!strcmp(var, "i18n.commitencoding")) if (!strcmp(var, "i18n.commitencoding")) {
FREE_AND_NULL(git_commit_encoding);
return git_config_string(&git_commit_encoding, var, value); return git_config_string(&git_commit_encoding, var, value);
}
if (!strcmp(var, "i18n.logoutputencoding")) if (!strcmp(var, "i18n.logoutputencoding")) {
FREE_AND_NULL(git_log_output_encoding);
return git_config_string(&git_log_output_encoding, var, value); return git_config_string(&git_log_output_encoding, var, value);
}
/* Add other config variables here and to Documentation/config.txt. */ /* Add other config variables here and to Documentation/config.txt. */
return 0; return 0;
@ -1766,10 +1780,15 @@ static int git_default_push_config(const char *var, const char *value)
static int git_default_mailmap_config(const char *var, const char *value) static int git_default_mailmap_config(const char *var, const char *value)
{ {
if (!strcmp(var, "mailmap.file")) if (!strcmp(var, "mailmap.file")) {
FREE_AND_NULL(git_mailmap_file);
return git_config_pathname(&git_mailmap_file, var, value); return git_config_pathname(&git_mailmap_file, var, value);
if (!strcmp(var, "mailmap.blob")) }
if (!strcmp(var, "mailmap.blob")) {
FREE_AND_NULL(git_mailmap_blob);
return git_config_string(&git_mailmap_blob, var, value); return git_config_string(&git_mailmap_blob, var, value);
}
/* Add other config variables here and to Documentation/config.txt. */ /* Add other config variables here and to Documentation/config.txt. */
return 0; return 0;
@ -1777,8 +1796,10 @@ static int git_default_mailmap_config(const char *var, const char *value)
static int git_default_attr_config(const char *var, const char *value) static int git_default_attr_config(const char *var, const char *value)
{ {
if (!strcmp(var, "attr.tree")) if (!strcmp(var, "attr.tree")) {
FREE_AND_NULL(git_attr_tree);
return git_config_string(&git_attr_tree, var, value); return git_config_string(&git_attr_tree, var, value);
}
/* /*
* Add other attribute related config variables here and to * Add other attribute related config variables here and to
@ -2405,7 +2426,7 @@ int git_configset_get_string(struct config_set *set, const char *key, char **des
{ {
const char *value; const char *value;
if (!git_configset_get_value(set, key, &value, NULL)) if (!git_configset_get_value(set, key, &value, NULL))
return git_config_string((const char **)dest, key, value); return git_config_string(dest, key, value);
else else
return 1; return 1;
} }
@ -2483,7 +2504,7 @@ int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *d
return 1; return 1;
} }
int git_configset_get_pathname(struct config_set *set, const char *key, const char **dest) int git_configset_get_pathname(struct config_set *set, const char *key, char **dest)
{ {
const char *value; const char *value;
if (!git_configset_get_value(set, key, &value, NULL)) if (!git_configset_get_value(set, key, &value, NULL))
@ -2628,7 +2649,7 @@ int repo_config_get_maybe_bool(struct repository *repo,
} }
int repo_config_get_pathname(struct repository *repo, int repo_config_get_pathname(struct repository *repo,
const char *key, const char **dest) const char *key, char **dest)
{ {
int ret; int ret;
git_config_check_init(repo); git_config_check_init(repo);
@ -2727,7 +2748,7 @@ int git_config_get_maybe_bool(const char *key, int *dest)
return repo_config_get_maybe_bool(the_repository, key, dest); return repo_config_get_maybe_bool(the_repository, key, dest);
} }
int git_config_get_pathname(const char *key, const char **dest) int git_config_get_pathname(const char *key, char **dest)
{ {
return repo_config_get_pathname(the_repository, key, dest); return repo_config_get_pathname(the_repository, key, dest);
} }

View File

@ -280,13 +280,13 @@ int git_config_bool(const char *, const char *);
* Allocates and copies the value string into the `dest` parameter; if no * Allocates and copies the value string into the `dest` parameter; if no
* string is given, prints an error message and returns -1. * string is given, prints an error message and returns -1.
*/ */
int git_config_string(const char **, const char *, const char *); int git_config_string(char **, const char *, const char *);
/** /**
* Similar to `git_config_string`, but expands `~` or `~user` into the * Similar to `git_config_string`, but expands `~` or `~user` into the
* user's home directory when found at the beginning of the path. * user's home directory when found at the beginning of the path.
*/ */
int git_config_pathname(const char **, const char *, const char *); int git_config_pathname(char **, const char *, const char *);
int git_config_expiry_date(timestamp_t *, const char *, const char *); int git_config_expiry_date(timestamp_t *, const char *, const char *);
int git_config_color(char *, const char *, const char *); int git_config_color(char *, const char *, const char *);
@ -541,7 +541,7 @@ int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned lon
int git_configset_get_bool(struct config_set *cs, const char *key, int *dest); int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest); int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest); int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest); int git_configset_get_pathname(struct config_set *cs, const char *key, char **dest);
/* Functions for reading a repository's config */ /* Functions for reading a repository's config */
struct repository; struct repository;
@ -577,7 +577,7 @@ int repo_config_get_bool_or_int(struct repository *repo,
int repo_config_get_maybe_bool(struct repository *repo, int repo_config_get_maybe_bool(struct repository *repo,
const char *key, int *dest); const char *key, int *dest);
int repo_config_get_pathname(struct repository *repo, int repo_config_get_pathname(struct repository *repo,
const char *key, const char **dest); const char *key, char **dest);
/* /*
* Functions for reading protected config. By definition, protected * Functions for reading protected config. By definition, protected
@ -687,7 +687,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);
* Similar to `git_config_get_string`, but expands `~` or `~user` into * Similar to `git_config_get_string`, but expands `~` or `~user` into
* the user's home directory when found at the beginning of the path. * the user's home directory when found at the beginning of the path.
*/ */
int git_config_get_pathname(const char *key, const char **dest); int git_config_get_pathname(const char *key, char **dest);
int git_config_get_index_threads(int *dest); int git_config_get_index_threads(int *dest);
int git_config_get_split_index(void); int git_config_get_split_index(void);

View File

@ -345,30 +345,32 @@ static int check_roundtrip(const char *enc_name)
* space separated encodings (eg. "UTF-16, ASCII, CP1125"). * space separated encodings (eg. "UTF-16, ASCII, CP1125").
* Search for the given encoding in that string. * Search for the given encoding in that string.
*/ */
const char *found = strcasestr(check_roundtrip_encoding, enc_name); const char *encoding = check_roundtrip_encoding ?
check_roundtrip_encoding : "SHIFT-JIS";
const char *found = strcasestr(encoding, enc_name);
const char *next; const char *next;
int len; int len;
if (!found) if (!found)
return 0; return 0;
next = found + strlen(enc_name); next = found + strlen(enc_name);
len = strlen(check_roundtrip_encoding); len = strlen(encoding);
return (found && ( return (found && (
/* /*
* check that the found encoding is at the * Check that the found encoding is at the beginning of
* beginning of check_roundtrip_encoding or * encoding or that it is prefixed with a space or
* that it is prefixed with a space or comma * comma.
*/ */
found == check_roundtrip_encoding || ( found == encoding || (
(isspace(found[-1]) || found[-1] == ',') (isspace(found[-1]) || found[-1] == ',')
) )
) && ( ) && (
/* /*
* check that the found encoding is at the * Check that the found encoding is at the end of
* end of check_roundtrip_encoding or * encoding or that it is suffixed with a space
* that it is suffixed with a space or comma * or comma.
*/ */
next == check_roundtrip_encoding + len || ( next == encoding + len || (
next < check_roundtrip_encoding + len && next < encoding + len &&
(isspace(next[0]) || next[0] == ',') (isspace(next[0]) || next[0] == ',')
) )
)); ));
@ -979,9 +981,9 @@ int async_query_available_blobs(const char *cmd, struct string_list *available_p
static struct convert_driver { static struct convert_driver {
const char *name; const char *name;
struct convert_driver *next; struct convert_driver *next;
const char *smudge; char *smudge;
const char *clean; char *clean;
const char *process; char *process;
int required; int required;
} *user_convert, **user_convert_tail; } *user_convert, **user_convert_tail;

View File

@ -92,7 +92,7 @@ void convert_attrs(struct index_state *istate,
struct conv_attrs *ca, const char *path); struct conv_attrs *ca, const char *path);
extern enum eol core_eol; extern enum eol core_eol;
extern const char *check_roundtrip_encoding; extern char *check_roundtrip_encoding;
const char *get_cached_convert_stats_ascii(struct index_state *istate, const char *get_cached_convert_stats_ascii(struct index_state *istate,
const char *path); const char *path);
const char *get_wt_convert_stats_ascii(const char *path); const char *get_wt_convert_stats_ascii(const char *path);

View File

@ -313,7 +313,7 @@ struct island_load_data {
size_t nr; size_t nr;
size_t alloc; size_t alloc;
}; };
static const char *core_island_name; static char *core_island_name;
static void free_config_regexes(struct island_load_data *ild) static void free_config_regexes(struct island_load_data *ild)
{ {

20
diff.c
View File

@ -56,14 +56,14 @@ static int diff_color_moved_default;
static int diff_color_moved_ws_default; static int diff_color_moved_ws_default;
static int diff_context_default = 3; static int diff_context_default = 3;
static int diff_interhunk_context_default; static int diff_interhunk_context_default;
static const char *diff_word_regex_cfg; static char *diff_word_regex_cfg;
static const char *external_diff_cmd_cfg; static char *external_diff_cmd_cfg;
static const char *diff_order_file_cfg; static char *diff_order_file_cfg;
int diff_auto_refresh_index = 1; int diff_auto_refresh_index = 1;
static int diff_mnemonic_prefix; static int diff_mnemonic_prefix;
static int diff_no_prefix; static int diff_no_prefix;
static const char *diff_src_prefix = "a/"; static char *diff_src_prefix;
static const char *diff_dst_prefix = "b/"; static char *diff_dst_prefix;
static int diff_relative; static int diff_relative;
static int diff_stat_name_width; static int diff_stat_name_width;
static int diff_stat_graph_width; static int diff_stat_graph_width;
@ -411,9 +411,11 @@ int git_diff_ui_config(const char *var, const char *value,
return 0; return 0;
} }
if (!strcmp(var, "diff.srcprefix")) { if (!strcmp(var, "diff.srcprefix")) {
FREE_AND_NULL(diff_src_prefix);
return git_config_string(&diff_src_prefix, var, value); return git_config_string(&diff_src_prefix, var, value);
} }
if (!strcmp(var, "diff.dstprefix")) { if (!strcmp(var, "diff.dstprefix")) {
FREE_AND_NULL(diff_dst_prefix);
return git_config_string(&diff_dst_prefix, var, value); return git_config_string(&diff_dst_prefix, var, value);
} }
if (!strcmp(var, "diff.relative")) { if (!strcmp(var, "diff.relative")) {
@ -3433,8 +3435,8 @@ void diff_set_noprefix(struct diff_options *options)
void diff_set_default_prefix(struct diff_options *options) void diff_set_default_prefix(struct diff_options *options)
{ {
options->a_prefix = diff_src_prefix; options->a_prefix = diff_src_prefix ? diff_src_prefix : "a/";
options->b_prefix = diff_dst_prefix; options->b_prefix = diff_dst_prefix ? diff_dst_prefix : "b/";
} }
struct userdiff_driver *get_textconv(struct repository *r, struct userdiff_driver *get_textconv(struct repository *r,
@ -5371,8 +5373,8 @@ static int diff_opt_default_prefix(const struct option *opt,
BUG_ON_OPT_NEG(unset); BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(optarg); BUG_ON_OPT_ARG(optarg);
diff_src_prefix = "a/"; FREE_AND_NULL(diff_src_prefix);
diff_dst_prefix = "b/"; FREE_AND_NULL(diff_dst_prefix);
diff_set_default_prefix(options); diff_set_default_prefix(options);
return 0; return 0;
} }

View File

@ -42,12 +42,12 @@ int is_bare_repository_cfg = -1; /* unspecified */
int warn_ambiguous_refs = 1; int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1; int warn_on_object_refname_ambiguity = 1;
int repository_format_precious_objects; int repository_format_precious_objects;
const char *git_commit_encoding; char *git_commit_encoding;
const char *git_log_output_encoding; char *git_log_output_encoding;
char *apply_default_whitespace; char *apply_default_whitespace;
char *apply_default_ignorewhitespace; char *apply_default_ignorewhitespace;
const char *git_attributes_file; char *git_attributes_file;
const char *git_hooks_path; char *git_hooks_path;
int zlib_compression_level = Z_BEST_SPEED; int zlib_compression_level = Z_BEST_SPEED;
int pack_compression_level = Z_DEFAULT_COMPRESSION; int pack_compression_level = Z_DEFAULT_COMPRESSION;
int fsync_object_files = -1; int fsync_object_files = -1;
@ -58,13 +58,13 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT; size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
size_t delta_base_cache_limit = 96 * 1024 * 1024; size_t delta_base_cache_limit = 96 * 1024 * 1024;
unsigned long big_file_threshold = 512 * 1024 * 1024; unsigned long big_file_threshold = 512 * 1024 * 1024;
const char *editor_program; char *editor_program;
const char *askpass_program; char *askpass_program;
const char *excludes_file; char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
enum eol core_eol = EOL_UNSET; enum eol core_eol = EOL_UNSET;
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN; int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
const char *check_roundtrip_encoding = "SHIFT-JIS"; char *check_roundtrip_encoding;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE; enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER; enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;

View File

@ -131,8 +131,8 @@ extern int warn_ambiguous_refs;
extern int warn_on_object_refname_ambiguity; extern int warn_on_object_refname_ambiguity;
extern char *apply_default_whitespace; extern char *apply_default_whitespace;
extern char *apply_default_ignorewhitespace; extern char *apply_default_ignorewhitespace;
extern const char *git_attributes_file; extern char *git_attributes_file;
extern const char *git_hooks_path; extern char *git_hooks_path;
extern int zlib_compression_level; extern int zlib_compression_level;
extern int pack_compression_level; extern int pack_compression_level;
extern size_t packed_git_window_size; extern size_t packed_git_window_size;
@ -224,12 +224,12 @@ int odb_pack_keep(const char *name);
const char *get_log_output_encoding(void); const char *get_log_output_encoding(void);
const char *get_commit_output_encoding(void); const char *get_commit_output_encoding(void);
extern const char *git_commit_encoding; extern char *git_commit_encoding;
extern const char *git_log_output_encoding; extern char *git_log_output_encoding;
extern const char *editor_program; extern char *editor_program;
extern const char *askpass_program; extern char *askpass_program;
extern const char *excludes_file; extern char *excludes_file;
/* /*
* Should we print an ellipsis after an abbreviated SHA-1 value * Should we print an ellipsis after an abbreviated SHA-1 value

View File

@ -1860,13 +1860,13 @@ static int fetch_pack_config_cb(const char *var, const char *value,
const char *msg_id; const char *msg_id;
if (strcmp(var, "fetch.fsck.skiplist") == 0) { if (strcmp(var, "fetch.fsck.skiplist") == 0) {
const char *path; char *path ;
if (git_config_pathname(&path, var, value)) if (git_config_pathname(&path, var, value))
return 1; return 1;
strbuf_addf(&fsck_msg_types, "%cskiplist=%s", strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
fsck_msg_types.len ? ',' : '=', path); fsck_msg_types.len ? ',' : '=', path);
free((char *)path); free(path);
return 0; return 0;
} }

4
fsck.c
View File

@ -1274,13 +1274,13 @@ int git_fsck_config(const char *var, const char *value,
const char *msg_id; const char *msg_id;
if (strcmp(var, "fsck.skiplist") == 0) { if (strcmp(var, "fsck.skiplist") == 0) {
const char *path; char *path;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
if (git_config_pathname(&path, var, value)) if (git_config_pathname(&path, var, value))
return 1; return 1;
strbuf_addf(&sb, "skiplist=%s", path); strbuf_addf(&sb, "skiplist=%s", path);
free((char *)path); free(path);
fsck_set_msg_types(options, sb.buf); fsck_set_msg_types(options, sb.buf);
strbuf_release(&sb); strbuf_release(&sb);
return 0; return 0;

View File

@ -103,6 +103,7 @@ static struct fsmonitor_settings *alloc_settings(void)
static void lookup_fsmonitor_settings(struct repository *r) static void lookup_fsmonitor_settings(struct repository *r)
{ {
const char *const_str; const char *const_str;
char *to_free = NULL;
int bool_value; int bool_value;
if (r->settings.fsmonitor) if (r->settings.fsmonitor)
@ -129,8 +130,9 @@ static void lookup_fsmonitor_settings(struct repository *r)
break; break;
case -1: /* config value set to an arbitrary string */ case -1: /* config value set to an arbitrary string */
if (repo_config_get_pathname(r, "core.fsmonitor", &const_str)) if (repo_config_get_pathname(r, "core.fsmonitor", &to_free))
return; /* should not happen */ return; /* should not happen */
const_str = to_free;
break; break;
default: /* should not happen */ default: /* should not happen */
@ -141,6 +143,7 @@ static void lookup_fsmonitor_settings(struct repository *r)
fsm_settings__set_hook(r, const_str); fsm_settings__set_hook(r, const_str);
else else
fsm_settings__set_disabled(r); fsm_settings__set_disabled(r);
free(to_free);
} }
enum fsmonitor_mode fsm_settings__get_mode(struct repository *r) enum fsmonitor_mode fsm_settings__get_mode(struct repository *r)

View File

@ -27,12 +27,14 @@ static void gpg_interface_lazy_init(void)
} }
static char *configured_signing_key; static char *configured_signing_key;
static const char *ssh_default_key_command, *ssh_allowed_signers, *ssh_revocation_file; static char *ssh_default_key_command;
static char *ssh_allowed_signers;
static char *ssh_revocation_file;
static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED; static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
struct gpg_format { struct gpg_format {
const char *name; const char *name;
const char *program; char *program;
const char **verify_args; const char **verify_args;
const char **sigs; const char **sigs;
int (*verify_signed_buffer)(struct signature_check *sigc, int (*verify_signed_buffer)(struct signature_check *sigc,

50
http.c
View File

@ -38,11 +38,11 @@ char curl_errorstr[CURL_ERROR_SIZE];
static int curl_ssl_verify = -1; static int curl_ssl_verify = -1;
static int curl_ssl_try; static int curl_ssl_try;
static const char *curl_http_version = NULL; static char *curl_http_version;
static const char *ssl_cert; static char *ssl_cert;
static const char *ssl_cert_type; static char *ssl_cert_type;
static const char *ssl_cipherlist; static char *ssl_cipherlist;
static const char *ssl_version; static char *ssl_version;
static struct { static struct {
const char *name; const char *name;
long ssl_version; long ssl_version;
@ -59,23 +59,23 @@ static struct {
{ "tlsv1.3", CURL_SSLVERSION_TLSv1_3 }, { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 },
#endif #endif
}; };
static const char *ssl_key; static char *ssl_key;
static const char *ssl_key_type; static char *ssl_key_type;
static const char *ssl_capath; static char *ssl_capath;
static const char *curl_no_proxy; static char *curl_no_proxy;
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY #ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
static const char *ssl_pinnedkey; static char *ssl_pinnedkey;
#endif #endif
static const char *ssl_cainfo; static char *ssl_cainfo;
static long curl_low_speed_limit = -1; static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1; static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv; static int curl_ftp_no_epsv;
static const char *curl_http_proxy; static char *curl_http_proxy;
static const char *http_proxy_authmethod; static char *http_proxy_authmethod;
static const char *http_proxy_ssl_cert; static char *http_proxy_ssl_cert;
static const char *http_proxy_ssl_key; static char *http_proxy_ssl_key;
static const char *http_proxy_ssl_ca_info; static char *http_proxy_ssl_ca_info;
static struct credential proxy_cert_auth = CREDENTIAL_INIT; static struct credential proxy_cert_auth = CREDENTIAL_INIT;
static int proxy_ssl_cert_password_required; static int proxy_ssl_cert_password_required;
@ -95,7 +95,7 @@ static struct {
*/ */
}; };
#ifdef CURLGSSAPI_DELEGATION_FLAG #ifdef CURLGSSAPI_DELEGATION_FLAG
static const char *curl_deleg; static char *curl_deleg;
static struct { static struct {
const char *name; const char *name;
long curl_deleg_param; long curl_deleg_param;
@ -108,11 +108,11 @@ static struct {
static struct credential proxy_auth = CREDENTIAL_INIT; static struct credential proxy_auth = CREDENTIAL_INIT;
static const char *curl_proxyuserpwd; static const char *curl_proxyuserpwd;
static const char *curl_cookie_file; static char *curl_cookie_file;
static int curl_save_cookies; static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT; struct credential http_auth = CREDENTIAL_INIT;
static int http_proactive_auth; static int http_proactive_auth;
static const char *user_agent; static char *user_agent;
static int curl_empty_auth = -1; static int curl_empty_auth = -1;
enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL; enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
@ -592,10 +592,10 @@ static void init_curl_http_auth(CURL *result)
} }
/* *var must be free-able */ /* *var must be free-able */
static void var_override(const char **var, char *value) static void var_override(char **var, char *value)
{ {
if (value) { if (value) {
free((void *)*var); free(*var);
*var = xstrdup(value); *var = xstrdup(value);
} }
} }
@ -1233,11 +1233,13 @@ static CURL *get_curl_handle(void)
return result; return result;
} }
static void set_from_env(const char **var, const char *envname) static void set_from_env(char **var, const char *envname)
{ {
const char *val = getenv(envname); const char *val = getenv(envname);
if (val) if (val) {
*var = val; FREE_AND_NULL(*var);
*var = xstrdup(val);
}
} }
void http_init(struct remote *remote, const char *url, int proactive_auth) void http_init(struct remote *remote, const char *url, int proactive_auth)

View File

@ -70,16 +70,16 @@ static char *next_arg(char **);
struct imap_server_conf { struct imap_server_conf {
const char *name; const char *name;
const char *tunnel; char *tunnel;
const char *host; char *host;
int port; int port;
const char *folder; char *folder;
const char *user; char *user;
const char *pass; char *pass;
int use_ssl; int use_ssl;
int ssl_verify; int ssl_verify;
int use_html; int use_html;
const char *auth_method; char *auth_method;
}; };
static struct imap_server_conf server = { static struct imap_server_conf server = {

View File

@ -6,8 +6,8 @@
#include "object-store-ll.h" #include "object-store-ll.h"
#include "setup.h" #include "setup.h"
const char *git_mailmap_file; char *git_mailmap_file;
const char *git_mailmap_blob; char *git_mailmap_blob;
struct mailmap_info { struct mailmap_info {
char *name; char *name;

View File

@ -3,8 +3,8 @@
struct string_list; struct string_list;
extern const char *git_mailmap_file; extern char *git_mailmap_file;
extern const char *git_mailmap_blob; extern char *git_mailmap_blob;
int read_mailmap(struct string_list *map); int read_mailmap(struct string_list *map);
void clear_mailmap(struct string_list *map); void clear_mailmap(struct string_list *map);

View File

@ -27,9 +27,9 @@ typedef enum ll_merge_result (*ll_merge_fn)(const struct ll_merge_driver *,
struct ll_merge_driver { struct ll_merge_driver {
const char *name; const char *name;
const char *description; char *description;
ll_merge_fn fn; ll_merge_fn fn;
const char *recursive; char *recursive;
struct ll_merge_driver *next; struct ll_merge_driver *next;
char *cmdline; char *cmdline;
}; };
@ -268,7 +268,7 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn,
* merge.default and merge.driver configuration items * merge.default and merge.driver configuration items
*/ */
static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail; static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
static const char *default_ll_merge; static char *default_ll_merge;
static int read_merge_config(const char *var, const char *value, static int read_merge_config(const char *var, const char *value,
const struct config_context *ctx UNUSED, const struct config_context *ctx UNUSED,

View File

@ -13,7 +13,7 @@ int pager_use_color = 1;
#endif #endif
static struct child_process pager_process; static struct child_process pager_process;
static const char *pager_program; static char *pager_program;
/* Is the value coming back from term_columns() just a guess? */ /* Is the value coming back from term_columns() just a guess? */
static int term_columns_guessed; static int term_columns_guessed;

View File

@ -62,7 +62,7 @@ static int git_pretty_formats_config(const char *var, const char *value,
{ {
struct cmt_fmt_map *commit_format = NULL; struct cmt_fmt_map *commit_format = NULL;
const char *name; const char *name;
const char *fmt; char *fmt;
int i; int i;
if (!skip_prefix(var, "pretty.", &name)) if (!skip_prefix(var, "pretty.", &name))
@ -93,13 +93,17 @@ static int git_pretty_formats_config(const char *var, const char *value,
if (git_config_string(&fmt, var, value)) if (git_config_string(&fmt, var, value))
return -1; return -1;
if (skip_prefix(fmt, "format:", &fmt)) if (skip_prefix(fmt, "format:", &commit_format->user_format)) {
commit_format->is_tformat = 0; commit_format->is_tformat = 0;
else if (skip_prefix(fmt, "tformat:", &fmt) || strchr(fmt, '%')) } else if (skip_prefix(fmt, "tformat:", &commit_format->user_format)) {
commit_format->is_tformat = 1; commit_format->is_tformat = 1;
else } else if (strchr(fmt, '%')) {
commit_format->is_tformat = 1;
commit_format->user_format = fmt;
} else {
commit_format->is_alias = 1; commit_format->is_alias = 1;
commit_format->user_format = fmt; commit_format->user_format = fmt;
}
return 0; return 0;
} }

View File

@ -13,7 +13,7 @@ struct object_id;
*/ */
struct promisor_remote { struct promisor_remote {
struct promisor_remote *next; struct promisor_remote *next;
const char *partial_clone_filter; char *partial_clone_filter;
const char name[FLEX_ARRAY]; const char name[FLEX_ARRAY];
}; };

View File

@ -430,29 +430,29 @@ static int handle_config(const char *key, const char *value,
else if (!strcmp(subkey, "prunetags")) else if (!strcmp(subkey, "prunetags"))
remote->prune_tags = git_config_bool(key, value); remote->prune_tags = git_config_bool(key, value);
else if (!strcmp(subkey, "url")) { else if (!strcmp(subkey, "url")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
add_url(remote, v); add_url(remote, v);
} else if (!strcmp(subkey, "pushurl")) { } else if (!strcmp(subkey, "pushurl")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
add_pushurl(remote, v); add_pushurl(remote, v);
} else if (!strcmp(subkey, "push")) { } else if (!strcmp(subkey, "push")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
refspec_append(&remote->push, v); refspec_append(&remote->push, v);
free((char *)v); free(v);
} else if (!strcmp(subkey, "fetch")) { } else if (!strcmp(subkey, "fetch")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
refspec_append(&remote->fetch, v); refspec_append(&remote->fetch, v);
free((char *)v); free(v);
} else if (!strcmp(subkey, "receivepack")) { } else if (!strcmp(subkey, "receivepack")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
if (!remote->receivepack) if (!remote->receivepack)
@ -460,7 +460,7 @@ static int handle_config(const char *key, const char *value,
else else
error(_("more than one receivepack given, using the first")); error(_("more than one receivepack given, using the first"));
} else if (!strcmp(subkey, "uploadpack")) { } else if (!strcmp(subkey, "uploadpack")) {
const char *v; char *v;
if (git_config_string(&v, key, value)) if (git_config_string(&v, key, value))
return -1; return -1;
if (!remote->uploadpack) if (!remote->uploadpack)
@ -473,10 +473,10 @@ static int handle_config(const char *key, const char *value,
else if (!strcmp(value, "--tags")) else if (!strcmp(value, "--tags"))
remote->fetch_tags = 2; remote->fetch_tags = 2;
} else if (!strcmp(subkey, "proxy")) { } else if (!strcmp(subkey, "proxy")) {
return git_config_string((const char **)&remote->http_proxy, return git_config_string(&remote->http_proxy,
key, value); key, value);
} else if (!strcmp(subkey, "proxyauthmethod")) { } else if (!strcmp(subkey, "proxyauthmethod")) {
return git_config_string((const char **)&remote->http_proxy_authmethod, return git_config_string(&remote->http_proxy_authmethod,
key, value); key, value);
} else if (!strcmp(subkey, "vcs")) { } else if (!strcmp(subkey, "vcs")) {
return git_config_string(&remote->foreign_vcs, key, value); return git_config_string(&remote->foreign_vcs, key, value);

View File

@ -46,7 +46,7 @@ struct remote_state {
struct hashmap branches_hash; struct hashmap branches_hash;
struct branch *current_branch; struct branch *current_branch;
const char *pushremote_name; char *pushremote_name;
struct rewrites rewrites; struct rewrites rewrites;
struct rewrites rewrites_push; struct rewrites rewrites_push;
@ -65,7 +65,7 @@ struct remote {
int origin, configured_in_repo; int origin, configured_in_repo;
const char *foreign_vcs; char *foreign_vcs;
/* An array of all of the url_nr URLs configured for the remote */ /* An array of all of the url_nr URLs configured for the remote */
const char **url; const char **url;
@ -309,9 +309,9 @@ struct branch {
const char *refname; const char *refname;
/* The name of the remote listed in the configuration. */ /* The name of the remote listed in the configuration. */
const char *remote_name; char *remote_name;
const char *pushremote_name; char *pushremote_name;
/* An array of the "merge" lines in the configuration. */ /* An array of the "merge" lines in the configuration. */
const char **merge_name; const char **merge_name;

View File

@ -306,7 +306,7 @@ static int git_sequencer_config(const char *k, const char *v,
} }
if (!opts->default_strategy && !strcmp(k, "pull.twohead")) { if (!opts->default_strategy && !strcmp(k, "pull.twohead")) {
int ret = git_config_string((const char**)&opts->default_strategy, k, v); int ret = git_config_string(&opts->default_strategy, k, v);
if (ret == 0) { if (ret == 0) {
/* /*
* pull.twohead is allowed to be multi-valued; we only * pull.twohead is allowed to be multi-valued; we only

View File

@ -1230,13 +1230,13 @@ static int safe_directory_cb(const char *key, const char *value,
} else if (!strcmp(value, "*")) { } else if (!strcmp(value, "*")) {
data->is_safe = 1; data->is_safe = 1;
} else { } else {
const char *interpolated = NULL; char *interpolated = NULL;
if (!git_config_pathname(&interpolated, key, value) && if (!git_config_pathname(&interpolated, key, value) &&
!fspathcmp(data->path, interpolated ? interpolated : value)) !fspathcmp(data->path, interpolated ? interpolated : value))
data->is_safe = 1; data->is_safe = 1;
free((char *)interpolated); free(interpolated);
} }
return 0; return 0;
@ -1875,7 +1875,7 @@ static int template_dir_cb(const char *key, const char *value,
char *path = NULL; char *path = NULL;
FREE_AND_NULL(data->path); FREE_AND_NULL(data->path);
if (!git_config_pathname((const char **)&path, key, value)) if (!git_config_pathname(&path, key, value))
data->path = path ? path : xstrdup(value); data->path = path ? path : xstrdup(value);
} }

View File

@ -691,8 +691,10 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
int strbuf_appendwholeline(struct strbuf *sb, FILE *fp, int term) int strbuf_appendwholeline(struct strbuf *sb, FILE *fp, int term)
{ {
struct strbuf line = STRBUF_INIT; struct strbuf line = STRBUF_INIT;
if (strbuf_getwholeline(&line, fp, term)) if (strbuf_getwholeline(&line, fp, term)) {
strbuf_release(&line);
return EOF; return EOF;
}
strbuf_addbuf(sb, &line); strbuf_addbuf(sb, &line);
strbuf_release(&line); strbuf_release(&line);
return 0; return 0;

View File

@ -56,6 +56,26 @@ void strvec_pushv(struct strvec *array, const char **items)
strvec_push(array, *items); strvec_push(array, *items);
} }
const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement)
{
char *to_free;
if (idx >= array->nr)
BUG("index outside of array boundary");
to_free = (char *) array->v[idx];
array->v[idx] = xstrdup(replacement);
free(to_free);
return array->v[idx];
}
void strvec_remove(struct strvec *array, size_t idx)
{
if (idx >= array->nr)
BUG("index outside of array boundary");
free((char *)array->v[idx]);
memmove(array->v + idx, array->v + idx + 1, (array->nr - idx) * sizeof(char *));
array->nr--;
}
void strvec_pop(struct strvec *array) void strvec_pop(struct strvec *array)
{ {
if (!array->nr) if (!array->nr)

View File

@ -64,6 +64,19 @@ void strvec_pushl(struct strvec *, ...);
/* Push a null-terminated array of strings onto the end of the array. */ /* Push a null-terminated array of strings onto the end of the array. */
void strvec_pushv(struct strvec *, const char **); void strvec_pushv(struct strvec *, const char **);
/**
* Replace the value at the given index with a new value. The index must be
* valid. Returns a pointer to the inserted value.
*/
const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement);
/*
* Remove the value at the given index. The remainder of the array will be
* moved to fill the resulting gap. The provided index must point into the
* array.
*/
void strvec_remove(struct strvec *array, size_t idx);
/** /**
* Remove the final element from the array. If there are no * Remove the final element from the array. If there are no
* elements in the array, do nothing. * elements in the array, do nothing.

View File

@ -91,6 +91,8 @@ static void free_one_config(struct submodule_entry *entry)
free((void *) entry->config->path); free((void *) entry->config->path);
free((void *) entry->config->name); free((void *) entry->config->name);
free((void *) entry->config->branch); free((void *) entry->config->branch);
free((void *) entry->config->url);
free((void *) entry->config->ignore);
free((void *) entry->config->update_strategy.command); free((void *) entry->config->update_strategy.command);
free(entry->config); free(entry->config);
} }

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='basic credential helper tests' test_description='basic credential helper tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh . "$TEST_DIRECTORY"/lib-credential.sh

View File

@ -2,6 +2,7 @@
test_description='reftable HTTPD tests' test_description='reftable HTTPD tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-httpd.sh

View File

@ -2,6 +2,7 @@
test_description='read-tree can handle submodules' test_description='read-tree can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -7,6 +7,7 @@
test_description='Compatibility with $XDG_CONFIG_HOME/git/ files' test_description='Compatibility with $XDG_CONFIG_HOME/git/ files'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'read config: xdg file exists and ~/.gitconfig doesn'\''t' ' test_expect_success 'read config: xdg file exists and ~/.gitconfig doesn'\''t' '

View File

@ -2,6 +2,7 @@
test_description='Test the core.hooksPath configuration variable' test_description='Test the core.hooksPath configuration variable'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'set up a pre-commit hook in core.hooksPath' ' test_expect_success 'set up a pre-commit hook in core.hooksPath' '

View File

@ -4,6 +4,8 @@
# #
test_description='Test git update-ref and basic ref logging' test_description='Test git update-ref and basic ref logging'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
Z=$ZERO_OID Z=$ZERO_OID

View File

@ -2,6 +2,7 @@
test_description='checkout can handle submodules' test_description='checkout can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -4,6 +4,7 @@ test_description='checkout <branch>
Ensures that checkout on an unborn branch does what the user expects' Ensures that checkout on an unborn branch does what the user expects'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Is the current branch "refs/heads/$1"? # Is the current branch "refs/heads/$1"?

View File

@ -5,6 +5,7 @@ test_description='switch basic functionality'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -6,6 +6,7 @@ This test verifies the recurse-submodules feature correctly lists files from
submodules. submodules.
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup directory structure and submodules' ' test_expect_success 'setup directory structure and submodules' '

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='git branch display tests' test_description='git branch display tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh . "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -5,6 +5,7 @@ test_description='auto squash'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh . "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -2,6 +2,7 @@
test_description='rebase can handle submodules' test_description='rebase can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh
. "$TEST_DIRECTORY"/lib-rebase.sh . "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -5,6 +5,7 @@ test_description='cherry-pick can handle submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -2,6 +2,7 @@
test_description='revert can handle submodules' test_description='revert can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -8,6 +8,7 @@ test_description='Test of the various options to git rm.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Setup some files to be removed, some with funny characters # Setup some files to be removed, some with funny characters

View File

@ -2,6 +2,7 @@
test_description='stash can handle submodules' test_description='stash can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -3,9 +3,9 @@
# Copyright (c) 2005 Junio C Hamano # Copyright (c) 2005 Junio C Hamano
# #
test_description='Test rename detection in diff engine. test_description='Test rename detection in diff engine.'
' TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh . "$TEST_DIRECTORY"/lib-diff.sh

View File

@ -12,6 +12,7 @@ This test tries to verify the sanity of the --submodule option of git diff.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Tested non-UTF-8 encoding # Tested non-UTF-8 encoding

View File

@ -5,6 +5,7 @@
test_description='Move a binary file' test_description='Move a binary file'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh

View File

@ -9,6 +9,7 @@ This test tries to verify that add_submodule_odb works when the submodule was
initialized previously but the checkout has since been removed. initialized previously but the checkout has since been removed.
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Tested non-UTF-8 encoding # Tested non-UTF-8 encoding

View File

@ -10,6 +10,7 @@ test_description='Support for diff format verbose submodule difference in git di
This test tries to verify the sanity of --submodule=diff option of git diff. This test tries to verify the sanity of --submodule=diff option of git diff.
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Tested non-UTF-8 encoding # Tested non-UTF-8 encoding

View File

@ -5,6 +5,7 @@
test_description='git apply -p handling.' test_description='git apply -p handling.'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success setup ' test_expect_success setup '

View File

@ -2,6 +2,7 @@
test_description='git apply handling submodules' test_description='git apply handling submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='test log with i18n features' test_description='test log with i18n features'
TEST_PASSES_SANITIZE_LEAK=true
. ./lib-gettext.sh . ./lib-gettext.sh
# two forms of é # two forms of é

View File

@ -2,6 +2,7 @@
test_description='test http auth header and credential helper interop' test_description='test http auth header and credential helper interop'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-httpd.sh

View File

@ -2,6 +2,7 @@
test_description="test fetching through http proxy" test_description="test fetching through http proxy"
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-httpd.sh

View File

@ -4,6 +4,7 @@ test_description='test GIT_CURL_VERBOSE'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd start_httpd

View File

@ -8,6 +8,7 @@ test_description='git rev-list --pretty=format test'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh . "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -2,6 +2,7 @@
test_description='bisect can handle submodules' test_description='bisect can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -7,6 +7,7 @@ test_description='Test merge with directory/file conflicts'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'prepare repository' ' test_expect_success 'prepare repository' '

View File

@ -4,6 +4,7 @@ test_description='merging with large rename matrix'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
count() { count() {

View File

@ -22,6 +22,7 @@ test_description="merge cases"
# underscore notation is to differentiate different # underscore notation is to differentiate different
# files that might be renamed into each other's paths.) # files that might be renamed into each other's paths.)
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh . "$TEST_DIRECTORY"/lib-merge.sh

View File

@ -2,6 +2,7 @@
test_description="remember regular & dir renames in sequence of merges" test_description="remember regular & dir renames in sequence of merges"
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# #

View File

@ -2,6 +2,7 @@
test_description='merge can handle submodules' test_description='merge can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='git mv in subdirs' test_description='git mv in subdirs'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff-data.sh . "$TEST_DIRECTORY"/lib-diff-data.sh

View File

@ -2,6 +2,7 @@
test_description='GIT_EDITOR, core.editor, and stuff' test_description='GIT_EDITOR, core.editor, and stuff'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
unset EDITOR VISUAL GIT_EDITOR unset EDITOR VISUAL GIT_EDITOR

View File

@ -10,6 +10,7 @@ Documented tests for git reset'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
commit_msg () { commit_msg () {

View File

@ -2,6 +2,7 @@
test_description='reset can handle submodules' test_description='reset can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh

View File

@ -4,6 +4,7 @@ test_description='check handling of .gitmodule path with dash'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -10,6 +10,7 @@ while making sure to add submodules using `git submodule add` instead of
`git add` as done in t7401. `git add` as done in t7401.
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -4,7 +4,6 @@
test_description='git svn honors i18n.commitEncoding in config' test_description='git svn honors i18n.commitEncoding in config'
TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh . ./lib-git-svn.sh
compare_git_head_with () { compare_git_head_with () {

View File

@ -4,7 +4,6 @@
test_description='git svn refuses to dcommit non-UTF8 messages' test_description='git svn refuses to dcommit non-UTF8 messages'
TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh . ./lib-git-svn.sh
# ISO-2022-JP can pass for valid UTF-8, so skipping that in this test # ISO-2022-JP can pass for valid UTF-8, so skipping that in this test

269
t/unit-tests/t-strvec.c Normal file
View File

@ -0,0 +1,269 @@
#include "test-lib.h"
#include "strbuf.h"
#include "strvec.h"
#define check_strvec(vec, ...) \
check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__)
static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
{
va_list ap;
size_t nr = 0;
va_start(ap, vec);
while (1) {
const char *str = va_arg(ap, const char *);
if (!str)
break;
if (!check_uint(vec->nr, >, nr) ||
!check_uint(vec->alloc, >, nr) ||
!check_str(vec->v[nr], str)) {
struct strbuf msg = STRBUF_INIT;
strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
test_assert(loc, msg.buf, 0);
strbuf_release(&msg);
return;
}
nr++;
}
check_uint(vec->nr, ==, nr);
check_uint(vec->alloc, >=, nr);
check_pointer_eq(vec->v[nr], NULL);
}
static void t_static_init(void)
{
struct strvec vec = STRVEC_INIT;
check_pointer_eq(vec.v, empty_strvec);
check_uint(vec.nr, ==, 0);
check_uint(vec.alloc, ==, 0);
}
static void t_dynamic_init(void)
{
struct strvec vec;
strvec_init(&vec);
check_pointer_eq(vec.v, empty_strvec);
check_uint(vec.nr, ==, 0);
check_uint(vec.alloc, ==, 0);
}
static void t_clear(void)
{
struct strvec vec = STRVEC_INIT;
strvec_push(&vec, "foo");
strvec_clear(&vec);
check_pointer_eq(vec.v, empty_strvec);
check_uint(vec.nr, ==, 0);
check_uint(vec.alloc, ==, 0);
}
static void t_push(void)
{
struct strvec vec = STRVEC_INIT;
strvec_push(&vec, "foo");
check_strvec(&vec, "foo", NULL);
strvec_push(&vec, "bar");
check_strvec(&vec, "foo", "bar", NULL);
strvec_clear(&vec);
}
static void t_pushf(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushf(&vec, "foo: %d", 1);
check_strvec(&vec, "foo: 1", NULL);
strvec_clear(&vec);
}
static void t_pushl(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
check_strvec(&vec, "foo", "bar", "baz", NULL);
strvec_clear(&vec);
}
static void t_pushv(void)
{
const char *strings[] = {
"foo", "bar", "baz", NULL,
};
struct strvec vec = STRVEC_INIT;
strvec_pushv(&vec, strings);
check_strvec(&vec, "foo", "bar", "baz", NULL);
strvec_clear(&vec);
}
static void t_replace_at_head(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_replace(&vec, 0, "replaced");
check_strvec(&vec, "replaced", "bar", "baz", NULL);
strvec_clear(&vec);
}
static void t_replace_at_tail(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_replace(&vec, 2, "replaced");
check_strvec(&vec, "foo", "bar", "replaced", NULL);
strvec_clear(&vec);
}
static void t_replace_in_between(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_replace(&vec, 1, "replaced");
check_strvec(&vec, "foo", "replaced", "baz", NULL);
strvec_clear(&vec);
}
static void t_replace_with_substring(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", NULL);
strvec_replace(&vec, 0, vec.v[0] + 1);
check_strvec(&vec, "oo", NULL);
strvec_clear(&vec);
}
static void t_remove_at_head(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_remove(&vec, 0);
check_strvec(&vec, "bar", "baz", NULL);
strvec_clear(&vec);
}
static void t_remove_at_tail(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_remove(&vec, 2);
check_strvec(&vec, "foo", "bar", NULL);
strvec_clear(&vec);
}
static void t_remove_in_between(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_remove(&vec, 1);
check_strvec(&vec, "foo", "baz", NULL);
strvec_clear(&vec);
}
static void t_pop_empty_array(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pop(&vec);
check_strvec(&vec, NULL);
strvec_clear(&vec);
}
static void t_pop_non_empty_array(void)
{
struct strvec vec = STRVEC_INIT;
strvec_pushl(&vec, "foo", "bar", "baz", NULL);
strvec_pop(&vec);
check_strvec(&vec, "foo", "bar", NULL);
strvec_clear(&vec);
}
static void t_split_empty_string(void)
{
struct strvec vec = STRVEC_INIT;
strvec_split(&vec, "");
check_strvec(&vec, NULL);
strvec_clear(&vec);
}
static void t_split_single_item(void)
{
struct strvec vec = STRVEC_INIT;
strvec_split(&vec, "foo");
check_strvec(&vec, "foo", NULL);
strvec_clear(&vec);
}
static void t_split_multiple_items(void)
{
struct strvec vec = STRVEC_INIT;
strvec_split(&vec, "foo bar baz");
check_strvec(&vec, "foo", "bar", "baz", NULL);
strvec_clear(&vec);
}
static void t_split_whitespace_only(void)
{
struct strvec vec = STRVEC_INIT;
strvec_split(&vec, " \t\n");
check_strvec(&vec, NULL);
strvec_clear(&vec);
}
static void t_split_multiple_consecutive_whitespaces(void)
{
struct strvec vec = STRVEC_INIT;
strvec_split(&vec, "foo\n\t bar");
check_strvec(&vec, "foo", "bar", NULL);
strvec_clear(&vec);
}
static void t_detach(void)
{
struct strvec vec = STRVEC_INIT;
const char **detached;
strvec_push(&vec, "foo");
detached = strvec_detach(&vec);
check_str(detached[0], "foo");
check_pointer_eq(detached[1], NULL);
check_pointer_eq(vec.v, empty_strvec);
check_uint(vec.nr, ==, 0);
check_uint(vec.alloc, ==, 0);
free((char *) detached[0]);
free(detached);
}
int cmd_main(int argc, const char **argv)
{
TEST(t_static_init(), "static initialization");
TEST(t_dynamic_init(), "dynamic initialization");
TEST(t_clear(), "clear");
TEST(t_push(), "push");
TEST(t_pushf(), "pushf");
TEST(t_pushl(), "pushl");
TEST(t_pushv(), "pushv");
TEST(t_replace_at_head(), "replace at head");
TEST(t_replace_in_between(), "replace in between");
TEST(t_replace_at_tail(), "replace at tail");
TEST(t_replace_with_substring(), "replace with substring");
TEST(t_remove_at_head(), "remove at head");
TEST(t_remove_in_between(), "remove in between");
TEST(t_remove_at_tail(), "remove at tail");
TEST(t_pop_empty_array(), "pop with empty array");
TEST(t_pop_non_empty_array(), "pop with non-empty array");
TEST(t_split_empty_string(), "split empty string");
TEST(t_split_single_item(), "split single item");
TEST(t_split_multiple_items(), "split multiple items");
TEST(t_split_whitespace_only(), "split whitespace only");
TEST(t_split_multiple_consecutive_whitespaces(), "split multiple consecutive whitespaces");
TEST(t_detach(), "detach");
return test_done();
}

View File

@ -318,6 +318,19 @@ int check_bool_loc(const char *loc, const char *check, int ok)
union test__tmp test__tmp[2]; union test__tmp test__tmp[2];
int check_pointer_eq_loc(const char *loc, const char *check, int ok,
const void *a, const void *b)
{
int ret = test_assert(loc, check, ok);
if (!ret) {
test_msg(" left: %p", a);
test_msg(" right: %p", b);
}
return ret;
}
int check_int_loc(const char *loc, const char *check, int ok, int check_int_loc(const char *loc, const char *check, int ok,
intmax_t a, intmax_t b) intmax_t a, intmax_t b)
{ {

View File

@ -75,6 +75,18 @@ int test_assert(const char *location, const char *check, int ok);
check_bool_loc(TEST_LOCATION(), #x, x) check_bool_loc(TEST_LOCATION(), #x, x)
int check_bool_loc(const char *loc, const char *check, int ok); int check_bool_loc(const char *loc, const char *check, int ok);
/*
* Compare two integers. Prints a message with the two values if the
* comparison fails. NB this is not thread safe.
*/
#define check_pointer_eq(a, b) \
(test__tmp[0].p = (a), test__tmp[1].p = (b), \
check_pointer_eq_loc(TEST_LOCATION(), #a" == "#b, \
test__tmp[0].p == test__tmp[1].p, \
test__tmp[0].p, test__tmp[1].p))
int check_pointer_eq_loc(const char *loc, const char *check, int ok,
const void *a, const void *b);
/* /*
* Compare two integers. Prints a message with the two values if the * Compare two integers. Prints a message with the two values if the
* comparison fails. NB this is not thread safe. * comparison fails. NB this is not thread safe.
@ -136,6 +148,7 @@ union test__tmp {
intmax_t i; intmax_t i;
uintmax_t u; uintmax_t u;
char c; char c;
const void *p;
}; };
extern union test__tmp test__tmp[2]; extern union test__tmp test__tmp[2];

View File

@ -22,7 +22,7 @@
static int debug; static int debug;
struct helper_data { struct helper_data {
const char *name; char *name;
struct child_process *helper; struct child_process *helper;
FILE *out; FILE *out;
unsigned fetch : 1, unsigned fetch : 1,
@ -111,6 +111,7 @@ static void do_take_over(struct transport *transport)
data = (struct helper_data *)transport->data; data = (struct helper_data *)transport->data;
transport_take_over(transport, data->helper); transport_take_over(transport, data->helper);
fclose(data->out); fclose(data->out);
free(data->name);
free(data); free(data);
} }
@ -253,6 +254,7 @@ static int disconnect_helper(struct transport *transport)
close(data->helper->out); close(data->helper->out);
fclose(data->out); fclose(data->out);
res = finish_command(data->helper); res = finish_command(data->helper);
FREE_AND_NULL(data->name);
FREE_AND_NULL(data->helper); FREE_AND_NULL(data->helper);
} }
return res; return res;
@ -1297,7 +1299,7 @@ static struct transport_vtable vtable = {
int transport_helper_init(struct transport *transport, const char *name) int transport_helper_init(struct transport *transport, const char *name)
{ {
struct helper_data *data = xcalloc(1, sizeof(*data)); struct helper_data *data = xcalloc(1, sizeof(*data));
data->name = name; data->name = xstrdup(name);
transport_check_allowed(name); transport_check_allowed(name);

View File

@ -1176,6 +1176,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
int len = external_specification_len(url); int len = external_specification_len(url);
char *handler = xmemdupz(url, len); char *handler = xmemdupz(url, len);
transport_helper_init(ret, handler); transport_helper_init(ret, handler);
free(handler);
} }
if (ret->smart_options) { if (ret->smart_options) {

View File

@ -94,7 +94,7 @@ struct upload_pack_data {
struct packet_writer writer; struct packet_writer writer;
const char *pack_objects_hook; char *pack_objects_hook;
unsigned stateless_rpc : 1; /* v0 only */ unsigned stateless_rpc : 1; /* v0 only */
unsigned no_done : 1; /* v0 only */ unsigned no_done : 1; /* v0 only */

View File

@ -7,19 +7,19 @@ struct index_state;
struct repository; struct repository;
struct userdiff_funcname { struct userdiff_funcname {
const char *pattern; char *pattern;
int cflags; int cflags;
}; };
struct userdiff_driver { struct userdiff_driver {
const char *name; const char *name;
const char *external; char *external;
const char *algorithm; char *algorithm;
int binary; int binary;
struct userdiff_funcname funcname; struct userdiff_funcname funcname;
const char *word_regex; char *word_regex;
const char *word_regex_multi_byte; char *word_regex_multi_byte;
const char *textconv; char *textconv;
struct notes_cache *textconv_cache; struct notes_cache *textconv_cache;
int textconv_want_cache; int textconv_want_cache;
}; };