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-strbuf
UNIT_TEST_PROGRAMS += t-strcmp-offset
UNIT_TEST_PROGRAMS += t-strvec
UNIT_TEST_PROGRAMS += t-trailer
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(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;
if (data->alias) {
if (!strcasecmp(p, data->alias))
return git_config_string((const char **)&data->v,
if (!strcasecmp(p, data->alias)) {
FREE_AND_NULL(data->v);
return git_config_string(&data->v,
key, value);
}
} else if (data->list) {
string_list_append(data->list, p);
}

2
attr.c
View file

@ -25,7 +25,7 @@
#include "tree-walk.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__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. */
int git_attr_system_is_enabled(void);
extern const char *git_attr_tree;
extern char *git_attr_tree;
#endif /* ATTR_H */

View file

@ -718,7 +718,7 @@ static int git_blame_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "blame.ignorerevsfile")) {
const char *str;
char *str;
int ret;
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,
struct object_id *rev,
int could_be_checkout_paths)
static char *parse_remote_branch(const char *arg,
struct object_id *rev,
int could_be_checkout_paths)
{
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) {
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;
int argcount = 0;
const char *arg;
char *remote = NULL;
int dash_dash_pos;
int has_dash_dash = 0;
int i;
@ -1416,8 +1417,8 @@ static int parse_branchname_arg(int argc, const char **argv,
recover_with_dwim = 0;
if (recover_with_dwim) {
const char *remote = parse_remote_branch(arg, rev,
could_be_checkout_paths);
remote = parse_remote_branch(arg, rev,
could_be_checkout_paths);
if (remote) {
*new_branch = arg;
arg = remote;
@ -1459,6 +1460,7 @@ static int parse_branchname_arg(int argc, const char **argv,
argc--;
}
free(remote);
return argcount;
}

View file

@ -107,7 +107,7 @@ static enum {
} commit_style;
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 commit message and/or authorship.
@ -133,7 +133,7 @@ static struct strvec trailer_args = STRVEC_INIT;
* is specified explicitly.
*/
static enum commit_msg_cleanup_mode cleanup_mode;
static const char *cleanup_arg;
static char *cleanup_arg;
static enum commit_whence whence;
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
strbuf_addstr(buf, v ? "true" : "false");
} else if (opts->type == TYPE_PATH) {
const char *v;
char *v;
if (git_config_pathname(&v, key_, value_) < 0)
return -1;
strbuf_addstr(buf, v);

View file

@ -39,5 +39,7 @@ int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
} else {
usage(usage_msg);
}
credential_clear(&c);
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 },
};
static const char *pull_twohead, *pull_octopus;
static char *pull_twohead, *pull_octopus;
enum ff_type {
FF_NO,
@ -110,7 +110,7 @@ enum ff_type {
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 int option_parse_message(const struct option *opt,

View file

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

View file

@ -83,7 +83,7 @@ static const char *action_names[] = {
struct rebase_options {
enum rebase_type type;
enum empty_type empty;
const char *default_backend;
char *default_backend;
const char *state_dir;
struct commit *upstream;
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 signature_check sigcheck;
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 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) {
const char *path;
char *path;
if (git_config_pathname(&path, var, value))
return 1;
strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
fsck_msg_types.len ? ',' : '=', path);
free((char *)path);
free(path);
return 0;
}

View file

@ -48,10 +48,10 @@ static const char incremental_bitmap_conflict_error[] = N_(
);
struct pack_objects_args {
const char *window;
const char *window_memory;
const char *depth;
const char *threads;
char *window;
char *window_memory;
char *depth;
char *threads;
unsigned long max_pack_size;
int no_reuse_delta;
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;
}
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 branch_exists;
const char *s = worktree_basename(path, &n);
const char *branchname = xstrndup(s, n);
char *branchname = xstrndup(s, n);
struct strbuf ref = STRBUF_INIT;
UNLEAK(branchname);
branch_exists = !strbuf_check_branch_ref(&ref, branchname) &&
refs_ref_exists(get_main_ref_store(the_repository),
ref.buf);
@ -756,8 +754,7 @@ static const char *dwim_branch(const char *path, const char **new_branch)
*new_branch = branchname;
if (guess_remote) {
struct object_id oid;
const char *remote =
unique_tracking_name(*new_branch, &oid, NULL);
char *remote = unique_tracking_name(*new_branch, &oid, NULL);
return remote;
}
return NULL;
@ -769,6 +766,8 @@ static int add(int ac, const char **av, const char *prefix)
const char *new_branch_force = NULL;
char *path;
const char *branch;
char *branch_to_free = NULL;
char *new_branch_to_free = NULL;
const char *new_branch = NULL;
const char *opt_track = 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);
} else if (ac < 2) {
/* 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)
branch = s;
branch = branch_to_free = s;
new_branch = new_branch_to_free;
/* DWIM: Infer --orphan when repo has no refs. */
opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1);
} else if (ac == 2) {
struct object_id oid;
struct commit *commit;
const char *remote;
char *remote;
commit = lookup_commit_reference_by_name(branch);
if (!commit) {
@ -923,6 +923,8 @@ static int add(int ac, const char **av, const char *prefix)
ret = add_worktree(path, branch, &opts);
free(path);
free(branch_to_free);
free(new_branch_to_free);
return ret;
}

View file

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

View file

@ -8,8 +8,8 @@
* tracking branch. Return the name of the remote if such a branch
* exists, NULL otherwise.
*/
const char *unique_tracking_name(const char *name,
struct object_id *oid,
int *dwim_remotes_matched);
char *unique_tracking_name(const char *name,
struct object_id *oid,
int *dwim_remotes_matched);
#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(). */
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_prio_queue(&queue);
}

View file

@ -1338,7 +1338,7 @@ int git_config_bool(const char *name, const char *value)
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)
return config_error_nonbool(var);
@ -1346,7 +1346,7 @@ int git_config_string(const char **dest, const char *var, const char *value)
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)
return config_error_nonbool(var);
@ -1414,11 +1414,15 @@ static int git_default_core_config(const char *var, const char *value,
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);
}
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);
}
if (!strcmp(var, "core.bare")) {
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;
}
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);
}
if (!strcmp(var, "core.notesref")) {
if (!value)
@ -1563,8 +1569,10 @@ static int git_default_core_config(const char *var, const char *value,
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);
}
if (!strcmp(var, "core.commentchar") ||
!strcmp(var, "core.commentstring")) {
@ -1582,11 +1590,13 @@ static int git_default_core_config(const char *var, const char *value,
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);
}
if (!strcmp(var, "core.excludesfile")) {
free((char *)excludes_file);
FREE_AND_NULL(excludes_file);
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)
{
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);
}
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);
}
/* Add other config variables here and to Documentation/config.txt. */
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)
{
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);
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);
}
/* Add other config variables here and to Documentation/config.txt. */
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)
{
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);
}
/*
* 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;
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
return 1;
}
@ -2483,7 +2504,7 @@ int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *d
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;
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,
const char *key, const char **dest)
const char *key, char **dest)
{
int ret;
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);
}
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);
}

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
* 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
* 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_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_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_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 */
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,
const char *key, int *dest);
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
@ -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
* 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_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").
* 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;
int len;
if (!found)
return 0;
next = found + strlen(enc_name);
len = strlen(check_roundtrip_encoding);
len = strlen(encoding);
return (found && (
/*
* check that the found encoding is at the
* beginning of check_roundtrip_encoding or
* that it is prefixed with a space or comma
* Check that the found encoding is at the beginning of
* encoding or that it is prefixed with a space or
* comma.
*/
found == check_roundtrip_encoding || (
found == encoding || (
(isspace(found[-1]) || found[-1] == ',')
)
) && (
/*
* check that the found encoding is at the
* end of check_roundtrip_encoding or
* that it is suffixed with a space or comma
* Check that the found encoding is at the end of
* encoding or that it is suffixed with a space
* or comma.
*/
next == check_roundtrip_encoding + len || (
next < check_roundtrip_encoding + len &&
next == encoding + len || (
next < encoding + len &&
(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 {
const char *name;
struct convert_driver *next;
const char *smudge;
const char *clean;
const char *process;
char *smudge;
char *clean;
char *process;
int required;
} *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);
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 *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 alloc;
};
static const char *core_island_name;
static char *core_island_name;
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_context_default = 3;
static int diff_interhunk_context_default;
static const char *diff_word_regex_cfg;
static const char *external_diff_cmd_cfg;
static const char *diff_order_file_cfg;
static char *diff_word_regex_cfg;
static char *external_diff_cmd_cfg;
static char *diff_order_file_cfg;
int diff_auto_refresh_index = 1;
static int diff_mnemonic_prefix;
static int diff_no_prefix;
static const char *diff_src_prefix = "a/";
static const char *diff_dst_prefix = "b/";
static char *diff_src_prefix;
static char *diff_dst_prefix;
static int diff_relative;
static int diff_stat_name_width;
static int diff_stat_graph_width;
@ -411,9 +411,11 @@ int git_diff_ui_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "diff.srcprefix")) {
FREE_AND_NULL(diff_src_prefix);
return git_config_string(&diff_src_prefix, var, value);
}
if (!strcmp(var, "diff.dstprefix")) {
FREE_AND_NULL(diff_dst_prefix);
return git_config_string(&diff_dst_prefix, var, value);
}
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)
{
options->a_prefix = diff_src_prefix;
options->b_prefix = diff_dst_prefix;
options->a_prefix = diff_src_prefix ? diff_src_prefix : "a/";
options->b_prefix = diff_dst_prefix ? diff_dst_prefix : "b/";
}
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_ARG(optarg);
diff_src_prefix = "a/";
diff_dst_prefix = "b/";
FREE_AND_NULL(diff_src_prefix);
FREE_AND_NULL(diff_dst_prefix);
diff_set_default_prefix(options);
return 0;
}

View file

@ -42,12 +42,12 @@ int is_bare_repository_cfg = -1; /* unspecified */
int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1;
int repository_format_precious_objects;
const char *git_commit_encoding;
const char *git_log_output_encoding;
char *git_commit_encoding;
char *git_log_output_encoding;
char *apply_default_whitespace;
char *apply_default_ignorewhitespace;
const char *git_attributes_file;
const char *git_hooks_path;
char *git_attributes_file;
char *git_hooks_path;
int zlib_compression_level = Z_BEST_SPEED;
int pack_compression_level = Z_DEFAULT_COMPRESSION;
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 delta_base_cache_limit = 96 * 1024 * 1024;
unsigned long big_file_threshold = 512 * 1024 * 1024;
const char *editor_program;
const char *askpass_program;
const char *excludes_file;
char *editor_program;
char *askpass_program;
char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
enum eol core_eol = EOL_UNSET;
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 rebase_setup_type autorebase = AUTOREBASE_NEVER;
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 char *apply_default_whitespace;
extern char *apply_default_ignorewhitespace;
extern const char *git_attributes_file;
extern const char *git_hooks_path;
extern char *git_attributes_file;
extern char *git_hooks_path;
extern int zlib_compression_level;
extern int pack_compression_level;
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_commit_output_encoding(void);
extern const char *git_commit_encoding;
extern const char *git_log_output_encoding;
extern char *git_commit_encoding;
extern char *git_log_output_encoding;
extern const char *editor_program;
extern const char *askpass_program;
extern const char *excludes_file;
extern char *editor_program;
extern char *askpass_program;
extern char *excludes_file;
/*
* 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;
if (strcmp(var, "fetch.fsck.skiplist") == 0) {
const char *path;
char *path ;
if (git_config_pathname(&path, var, value))
return 1;
strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
fsck_msg_types.len ? ',' : '=', path);
free((char *)path);
free(path);
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;
if (strcmp(var, "fsck.skiplist") == 0) {
const char *path;
char *path;
struct strbuf sb = STRBUF_INIT;
if (git_config_pathname(&path, var, value))
return 1;
strbuf_addf(&sb, "skiplist=%s", path);
free((char *)path);
free(path);
fsck_set_msg_types(options, sb.buf);
strbuf_release(&sb);
return 0;

View file

@ -103,6 +103,7 @@ static struct fsmonitor_settings *alloc_settings(void)
static void lookup_fsmonitor_settings(struct repository *r)
{
const char *const_str;
char *to_free = NULL;
int bool_value;
if (r->settings.fsmonitor)
@ -129,8 +130,9 @@ static void lookup_fsmonitor_settings(struct repository *r)
break;
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 */
const_str = to_free;
break;
default: /* should not happen */
@ -141,6 +143,7 @@ static void lookup_fsmonitor_settings(struct repository *r)
fsm_settings__set_hook(r, const_str);
else
fsm_settings__set_disabled(r);
free(to_free);
}
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 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;
struct gpg_format {
const char *name;
const char *program;
char *program;
const char **verify_args;
const char **sigs;
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_try;
static const char *curl_http_version = NULL;
static const char *ssl_cert;
static const char *ssl_cert_type;
static const char *ssl_cipherlist;
static const char *ssl_version;
static char *curl_http_version;
static char *ssl_cert;
static char *ssl_cert_type;
static char *ssl_cipherlist;
static char *ssl_version;
static struct {
const char *name;
long ssl_version;
@ -59,23 +59,23 @@ static struct {
{ "tlsv1.3", CURL_SSLVERSION_TLSv1_3 },
#endif
};
static const char *ssl_key;
static const char *ssl_key_type;
static const char *ssl_capath;
static const char *curl_no_proxy;
static char *ssl_key;
static char *ssl_key_type;
static char *ssl_capath;
static char *curl_no_proxy;
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
static const char *ssl_pinnedkey;
static char *ssl_pinnedkey;
#endif
static const char *ssl_cainfo;
static char *ssl_cainfo;
static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
static const char *http_proxy_authmethod;
static char *curl_http_proxy;
static char *http_proxy_authmethod;
static const char *http_proxy_ssl_cert;
static const char *http_proxy_ssl_key;
static const char *http_proxy_ssl_ca_info;
static char *http_proxy_ssl_cert;
static char *http_proxy_ssl_key;
static char *http_proxy_ssl_ca_info;
static struct credential proxy_cert_auth = CREDENTIAL_INIT;
static int proxy_ssl_cert_password_required;
@ -95,7 +95,7 @@ static struct {
*/
};
#ifdef CURLGSSAPI_DELEGATION_FLAG
static const char *curl_deleg;
static char *curl_deleg;
static struct {
const char *name;
long curl_deleg_param;
@ -108,11 +108,11 @@ static struct {
static struct credential proxy_auth = CREDENTIAL_INIT;
static const char *curl_proxyuserpwd;
static const char *curl_cookie_file;
static char *curl_cookie_file;
static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
static int http_proactive_auth;
static const char *user_agent;
static char *user_agent;
static int curl_empty_auth = -1;
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 */
static void var_override(const char **var, char *value)
static void var_override(char **var, char *value)
{
if (value) {
free((void *)*var);
free(*var);
*var = xstrdup(value);
}
}
@ -1233,11 +1233,13 @@ static CURL *get_curl_handle(void)
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);
if (val)
*var = val;
if (val) {
FREE_AND_NULL(*var);
*var = xstrdup(val);
}
}
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 {
const char *name;
const char *tunnel;
const char *host;
char *tunnel;
char *host;
int port;
const char *folder;
const char *user;
const char *pass;
char *folder;
char *user;
char *pass;
int use_ssl;
int ssl_verify;
int use_html;
const char *auth_method;
char *auth_method;
};
static struct imap_server_conf server = {

View file

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

View file

@ -3,8 +3,8 @@
struct string_list;
extern const char *git_mailmap_file;
extern const char *git_mailmap_blob;
extern char *git_mailmap_file;
extern char *git_mailmap_blob;
int read_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 {
const char *name;
const char *description;
char *description;
ll_merge_fn fn;
const char *recursive;
char *recursive;
struct ll_merge_driver *next;
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
*/
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,
const struct config_context *ctx UNUSED,

View file

@ -13,7 +13,7 @@ int pager_use_color = 1;
#endif
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? */
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;
const char *name;
const char *fmt;
char *fmt;
int i;
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))
return -1;
if (skip_prefix(fmt, "format:", &fmt))
if (skip_prefix(fmt, "format:", &commit_format->user_format)) {
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;
else
} else if (strchr(fmt, '%')) {
commit_format->is_tformat = 1;
commit_format->user_format = fmt;
} else {
commit_format->is_alias = 1;
commit_format->user_format = fmt;
commit_format->user_format = fmt;
}
return 0;
}

View file

@ -13,7 +13,7 @@ struct object_id;
*/
struct promisor_remote {
struct promisor_remote *next;
const char *partial_clone_filter;
char *partial_clone_filter;
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"))
remote->prune_tags = git_config_bool(key, value);
else if (!strcmp(subkey, "url")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
add_url(remote, v);
} else if (!strcmp(subkey, "pushurl")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
add_pushurl(remote, v);
} else if (!strcmp(subkey, "push")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
refspec_append(&remote->push, v);
free((char *)v);
free(v);
} else if (!strcmp(subkey, "fetch")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
refspec_append(&remote->fetch, v);
free((char *)v);
free(v);
} else if (!strcmp(subkey, "receivepack")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
if (!remote->receivepack)
@ -460,7 +460,7 @@ static int handle_config(const char *key, const char *value,
else
error(_("more than one receivepack given, using the first"));
} else if (!strcmp(subkey, "uploadpack")) {
const char *v;
char *v;
if (git_config_string(&v, key, value))
return -1;
if (!remote->uploadpack)
@ -473,10 +473,10 @@ static int handle_config(const char *key, const char *value,
else if (!strcmp(value, "--tags"))
remote->fetch_tags = 2;
} else if (!strcmp(subkey, "proxy")) {
return git_config_string((const char **)&remote->http_proxy,
return git_config_string(&remote->http_proxy,
key, value);
} 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);
} else if (!strcmp(subkey, "vcs")) {
return git_config_string(&remote->foreign_vcs, key, value);

View file

@ -46,7 +46,7 @@ struct remote_state {
struct hashmap branches_hash;
struct branch *current_branch;
const char *pushremote_name;
char *pushremote_name;
struct rewrites rewrites;
struct rewrites rewrites_push;
@ -65,7 +65,7 @@ struct remote {
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 */
const char **url;
@ -309,9 +309,9 @@ struct branch {
const char *refname;
/* 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. */
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")) {
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) {
/*
* 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, "*")) {
data->is_safe = 1;
} else {
const char *interpolated = NULL;
char *interpolated = NULL;
if (!git_config_pathname(&interpolated, key, value) &&
!fspathcmp(data->path, interpolated ? interpolated : value))
data->is_safe = 1;
free((char *)interpolated);
free(interpolated);
}
return 0;
@ -1875,7 +1875,7 @@ static int template_dir_cb(const char *key, const char *value,
char *path = NULL;
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);
}

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)
{
struct strbuf line = STRBUF_INIT;
if (strbuf_getwholeline(&line, fp, term))
if (strbuf_getwholeline(&line, fp, term)) {
strbuf_release(&line);
return EOF;
}
strbuf_addbuf(sb, &line);
strbuf_release(&line);
return 0;

View file

@ -56,6 +56,26 @@ void strvec_pushv(struct strvec *array, const char **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)
{
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. */
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
* 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->name);
free((void *) entry->config->branch);
free((void *) entry->config->url);
free((void *) entry->config->ignore);
free((void *) entry->config->update_strategy.command);
free(entry->config);
}

View file

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

View file

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

View file

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

View file

@ -7,6 +7,7 @@
test_description='Compatibility with $XDG_CONFIG_HOME/git/ files'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
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_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
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_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
Z=$ZERO_OID

View file

@ -2,6 +2,7 @@
test_description='checkout can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.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'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# 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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@
test_description='rebase can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh

View file

@ -2,6 +2,7 @@
test_description='revert can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Setup some files to be removed, some with funny characters

View file

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

View file

@ -3,9 +3,9 @@
# 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_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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Tested non-UTF-8 encoding

View file

@ -5,6 +5,7 @@
test_description='Move a binary file'
TEST_PASSES_SANITIZE_LEAK=true
. ./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.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# 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.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Tested non-UTF-8 encoding

View file

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

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@
test_description="test fetching through http proxy"
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd

View file

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

View file

@ -2,6 +2,7 @@
test_description='bisect can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
count() {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@
test_description='reset can handle submodules'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.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
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
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.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View file

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

View file

@ -4,7 +4,6 @@
test_description='git svn refuses to dcommit non-UTF8 messages'
TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
# 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];
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,
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)
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
* comparison fails. NB this is not thread safe.
@ -136,6 +148,7 @@ union test__tmp {
intmax_t i;
uintmax_t u;
char c;
const void *p;
};
extern union test__tmp test__tmp[2];

View file

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

View file

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

View file

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