Git fork

argv-array: rename to strvec

The name "argv-array" isn't very good, because it describes what the
data type can be used for (program argument arrays), not what it
actually is (a dynamically-growing string array that maintains a
NULL-terminator invariant). This leads to people being hesitant to use
it for other cases where it would actually be a good fit. The existing
name is also clunky to use. It's overly long, and the name often leads
to saying things like "argv.argv" (i.e., the field names overlap with
variable names, since they're describing the use, not the type). Let's
give it a more neutral name.

I settled on "strvec" because "vector" is the name for a dynamic array
type in many programming languages. "strarray" would work, too, but it's
longer and a bit more awkward to say (and don't we all say these things
in our mind as we type them?).

A more extreme direction would be a generic data structure which stores
a NULL-terminated of _any_ type. That would be easy to do with void
pointers, but we'd lose some type safety for the existing cases. Plus it
raises questions about memory allocation and ownership. So I limited
myself here to changing names only, and not semantics. If we do find a
use for that more generic data type, we could perhaps implement it at a
lower level and then provide type-safe wrappers around it for strings.
But that can come later.

This patch does the minimum to convert the struct and function names in
the header and implementation, leaving a few things for follow-on
patches:

- files retain their original names for now

- struct field names are retained for now

- there's a preprocessor compat layer that lets most users remain the
same for now. The exception is headers which made a manual forward
declaration of the struct. I've converted them (and their dependent
function declarations) here.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Jeff King and committed by
Junio C Hamano
873cd28a 819f0e76

+74 -61
+22 -22
argv-array.c
··· 2 #include "argv-array.h" 3 #include "strbuf.h" 4 5 - const char *empty_argv[] = { NULL }; 6 7 - void argv_array_init(struct argv_array *array) 8 { 9 - array->argv = empty_argv; 10 array->argc = 0; 11 array->alloc = 0; 12 } 13 14 - static void argv_array_push_nodup(struct argv_array *array, const char *value) 15 { 16 - if (array->argv == empty_argv) 17 array->argv = NULL; 18 19 ALLOC_GROW(array->argv, array->argc + 2, array->alloc); ··· 21 array->argv[array->argc] = NULL; 22 } 23 24 - const char *argv_array_push(struct argv_array *array, const char *value) 25 { 26 - argv_array_push_nodup(array, xstrdup(value)); 27 return array->argv[array->argc - 1]; 28 } 29 30 - const char *argv_array_pushf(struct argv_array *array, const char *fmt, ...) 31 { 32 va_list ap; 33 struct strbuf v = STRBUF_INIT; ··· 36 strbuf_vaddf(&v, fmt, ap); 37 va_end(ap); 38 39 - argv_array_push_nodup(array, strbuf_detach(&v, NULL)); 40 return array->argv[array->argc - 1]; 41 } 42 43 - void argv_array_pushl(struct argv_array *array, ...) 44 { 45 va_list ap; 46 const char *arg; 47 48 va_start(ap, array); 49 while ((arg = va_arg(ap, const char *))) 50 - argv_array_push(array, arg); 51 va_end(ap); 52 } 53 54 - void argv_array_pushv(struct argv_array *array, const char **argv) 55 { 56 for (; *argv; argv++) 57 - argv_array_push(array, *argv); 58 } 59 60 - void argv_array_pop(struct argv_array *array) 61 { 62 if (!array->argc) 63 return; ··· 66 array->argc--; 67 } 68 69 - void argv_array_split(struct argv_array *array, const char *to_split) 70 { 71 while (isspace(*to_split)) 72 to_split++; ··· 78 79 while (*p && !isspace(*p)) 80 p++; 81 - argv_array_push_nodup(array, xstrndup(to_split, p - to_split)); 82 83 while (isspace(*p)) 84 p++; ··· 86 } 87 } 88 89 - void argv_array_clear(struct argv_array *array) 90 { 91 - if (array->argv != empty_argv) { 92 int i; 93 for (i = 0; i < array->argc; i++) 94 free((char *)array->argv[i]); 95 free(array->argv); 96 } 97 - argv_array_init(array); 98 } 99 100 - const char **argv_array_detach(struct argv_array *array) 101 { 102 - if (array->argv == empty_argv) 103 return xcalloc(1, sizeof(const char *)); 104 else { 105 const char **ret = array->argv; 106 - argv_array_init(array); 107 return ret; 108 } 109 }
··· 2 #include "argv-array.h" 3 #include "strbuf.h" 4 5 + const char *empty_strvec[] = { NULL }; 6 7 + void strvec_init(struct strvec *array) 8 { 9 + array->argv = empty_strvec; 10 array->argc = 0; 11 array->alloc = 0; 12 } 13 14 + static void strvec_push_nodup(struct strvec *array, const char *value) 15 { 16 + if (array->argv == empty_strvec) 17 array->argv = NULL; 18 19 ALLOC_GROW(array->argv, array->argc + 2, array->alloc); ··· 21 array->argv[array->argc] = NULL; 22 } 23 24 + const char *strvec_push(struct strvec *array, const char *value) 25 { 26 + strvec_push_nodup(array, xstrdup(value)); 27 return array->argv[array->argc - 1]; 28 } 29 30 + const char *strvec_pushf(struct strvec *array, const char *fmt, ...) 31 { 32 va_list ap; 33 struct strbuf v = STRBUF_INIT; ··· 36 strbuf_vaddf(&v, fmt, ap); 37 va_end(ap); 38 39 + strvec_push_nodup(array, strbuf_detach(&v, NULL)); 40 return array->argv[array->argc - 1]; 41 } 42 43 + void strvec_pushl(struct strvec *array, ...) 44 { 45 va_list ap; 46 const char *arg; 47 48 va_start(ap, array); 49 while ((arg = va_arg(ap, const char *))) 50 + strvec_push(array, arg); 51 va_end(ap); 52 } 53 54 + void strvec_pushv(struct strvec *array, const char **argv) 55 { 56 for (; *argv; argv++) 57 + strvec_push(array, *argv); 58 } 59 60 + void strvec_pop(struct strvec *array) 61 { 62 if (!array->argc) 63 return; ··· 66 array->argc--; 67 } 68 69 + void strvec_split(struct strvec *array, const char *to_split) 70 { 71 while (isspace(*to_split)) 72 to_split++; ··· 78 79 while (*p && !isspace(*p)) 80 p++; 81 + strvec_push_nodup(array, xstrndup(to_split, p - to_split)); 82 83 while (isspace(*p)) 84 p++; ··· 86 } 87 } 88 89 + void strvec_clear(struct strvec *array) 90 { 91 + if (array->argv != empty_strvec) { 92 int i; 93 for (i = 0; i < array->argc; i++) 94 free((char *)array->argv[i]); 95 free(array->argv); 96 } 97 + strvec_init(array); 98 } 99 100 + const char **strvec_detach(struct strvec *array) 101 { 102 + if (array->argv == empty_strvec) 103 return xcalloc(1, sizeof(const char *)); 104 else { 105 const char **ret = array->argv; 106 + strvec_init(array); 107 return ret; 108 } 109 }
+32 -19
argv-array.h
··· 14 * it contains an item structure with a `util` field that is not compatible 15 * with the traditional argv interface. 16 * 17 - * Each `argv_array` manages its own memory. Any strings pushed into the 18 - * array are duplicated, and all memory is freed by argv_array_clear(). 19 */ 20 21 - extern const char *empty_argv[]; 22 23 /** 24 * A single array. This should be initialized by assignment from 25 - * `ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv` 26 * member contains the actual array; the `argc` member contains the 27 * number of elements in the array, not including the terminating 28 * NULL. 29 */ 30 - struct argv_array { 31 const char **argv; 32 size_t argc; 33 size_t alloc; 34 }; 35 36 - #define ARGV_ARRAY_INIT { empty_argv, 0, 0 } 37 38 /** 39 * Initialize an array. This is no different than assigning from 40 - * `ARGV_ARRAY_INIT`. 41 */ 42 - void argv_array_init(struct argv_array *); 43 44 /* Push a copy of a string onto the end of the array. */ 45 - const char *argv_array_push(struct argv_array *, const char *); 46 47 /** 48 * Format a string and push it onto the end of the array. This is a 49 - * convenience wrapper combining `strbuf_addf` and `argv_array_push`. 50 */ 51 __attribute__((format (printf,2,3))) 52 - const char *argv_array_pushf(struct argv_array *, const char *fmt, ...); 53 54 /** 55 * Push a list of strings onto the end of the array. The arguments ··· 57 * argument. 58 */ 59 LAST_ARG_MUST_BE_NULL 60 - void argv_array_pushl(struct argv_array *, ...); 61 62 /* Push a null-terminated array of strings onto the end of the array. */ 63 - void argv_array_pushv(struct argv_array *, const char **); 64 65 /** 66 * Remove the final element from the array. If there are no 67 * elements in the array, do nothing. 68 */ 69 - void argv_array_pop(struct argv_array *); 70 71 /* Splits by whitespace; does not handle quoted arguments! */ 72 - void argv_array_split(struct argv_array *, const char *); 73 74 /** 75 * Free all memory associated with the array and return it to the 76 * initial, empty state. 77 */ 78 - void argv_array_clear(struct argv_array *); 79 80 /** 81 - * Disconnect the `argv` member from the `argv_array` struct and 82 * return it. The caller is responsible for freeing the memory used 83 * by the array, and by the strings it references. After detaching, 84 - * the `argv_array` is in a reinitialized state and can be pushed 85 * into again. 86 */ 87 - const char **argv_array_detach(struct argv_array *); 88 89 #endif /* ARGV_ARRAY_H */
··· 14 * it contains an item structure with a `util` field that is not compatible 15 * with the traditional argv interface. 16 * 17 + * Each `strvec` manages its own memory. Any strings pushed into the 18 + * array are duplicated, and all memory is freed by strvec_clear(). 19 */ 20 21 + extern const char *empty_strvec[]; 22 23 /** 24 * A single array. This should be initialized by assignment from 25 + * `STRVEC_INIT`, or by calling `strvec_init`. The `argv` 26 * member contains the actual array; the `argc` member contains the 27 * number of elements in the array, not including the terminating 28 * NULL. 29 */ 30 + struct strvec { 31 const char **argv; 32 size_t argc; 33 size_t alloc; 34 }; 35 36 + #define STRVEC_INIT { empty_strvec, 0, 0 } 37 38 /** 39 * Initialize an array. This is no different than assigning from 40 + * `STRVEC_INIT`. 41 */ 42 + void strvec_init(struct strvec *); 43 44 /* Push a copy of a string onto the end of the array. */ 45 + const char *strvec_push(struct strvec *, const char *); 46 47 /** 48 * Format a string and push it onto the end of the array. This is a 49 + * convenience wrapper combining `strbuf_addf` and `strvec_push`. 50 */ 51 __attribute__((format (printf,2,3))) 52 + const char *strvec_pushf(struct strvec *, const char *fmt, ...); 53 54 /** 55 * Push a list of strings onto the end of the array. The arguments ··· 57 * argument. 58 */ 59 LAST_ARG_MUST_BE_NULL 60 + void strvec_pushl(struct strvec *, ...); 61 62 /* Push a null-terminated array of strings onto the end of the array. */ 63 + void strvec_pushv(struct strvec *, const char **); 64 65 /** 66 * Remove the final element from the array. If there are no 67 * elements in the array, do nothing. 68 */ 69 + void strvec_pop(struct strvec *); 70 71 /* Splits by whitespace; does not handle quoted arguments! */ 72 + void strvec_split(struct strvec *, const char *); 73 74 /** 75 * Free all memory associated with the array and return it to the 76 * initial, empty state. 77 */ 78 + void strvec_clear(struct strvec *); 79 80 /** 81 + * Disconnect the `argv` member from the `strvec` struct and 82 * return it. The caller is responsible for freeing the memory used 83 * by the array, and by the strings it references. After detaching, 84 + * the `strvec` is in a reinitialized state and can be pushed 85 * into again. 86 */ 87 + const char **strvec_detach(struct strvec *); 88 + 89 + /* compatibility for historic argv_array interface */ 90 + #define argv_array strvec 91 + #define ARGV_ARRAY_INIT STRVEC_INIT 92 + #define argv_array_init strvec_init 93 + #define argv_array_push strvec_push 94 + #define argv_array_pushf strvec_pushf 95 + #define argv_array_pushl strvec_pushl 96 + #define argv_array_pushv strvec_pushv 97 + #define argv_array_pop strvec_pop 98 + #define argv_array_split strvec_split 99 + #define argv_array_clear strvec_clear 100 + #define argv_array_detach strvec_detach 101 102 #endif /* ARGV_ARRAY_H */
+2 -2
exec-cmd.h
··· 1 #ifndef GIT_EXEC_CMD_H 2 #define GIT_EXEC_CMD_H 3 4 - struct argv_array; 5 6 void git_set_exec_path(const char *exec_path); 7 void git_resolve_executable_dir(const char *path); 8 const char *git_exec_path(void); 9 void setup_path(void); 10 - const char **prepare_git_cmd(struct argv_array *out, const char **argv); 11 int execv_git_cmd(const char **argv); /* NULL terminated */ 12 LAST_ARG_MUST_BE_NULL 13 int execl_git_cmd(const char *cmd, ...);
··· 1 #ifndef GIT_EXEC_CMD_H 2 #define GIT_EXEC_CMD_H 3 4 + struct strvec; 5 6 void git_set_exec_path(const char *exec_path); 7 void git_resolve_executable_dir(const char *path); 8 const char *git_exec_path(void); 9 void setup_path(void); 10 + const char **prepare_git_cmd(struct strvec *out, const char **argv); 11 int execv_git_cmd(const char **argv); /* NULL terminated */ 12 LAST_ARG_MUST_BE_NULL 13 int execl_git_cmd(const char *cmd, ...);
+2 -2
ls-refs.h
··· 2 #define LS_REFS_H 3 4 struct repository; 5 - struct argv_array; 6 struct packet_reader; 7 - int ls_refs(struct repository *r, struct argv_array *keys, 8 struct packet_reader *request); 9 10 #endif /* LS_REFS_H */
··· 2 #define LS_REFS_H 3 4 struct repository; 5 + struct strvec; 6 struct packet_reader; 7 + int ls_refs(struct repository *r, struct strvec *keys, 8 struct packet_reader *request); 9 10 #endif /* LS_REFS_H */
+2 -2
quote.h
··· 60 * still modify arg in place, but unlike sq_dequote_to_argv, the argv_array 61 * will duplicate and take ownership of the strings. 62 */ 63 - struct argv_array; 64 - int sq_dequote_to_argv_array(char *arg, struct argv_array *); 65 66 int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); 67 size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
··· 60 * still modify arg in place, but unlike sq_dequote_to_argv, the argv_array 61 * will duplicate and take ownership of the strings. 62 */ 63 + struct strvec; 64 + int sq_dequote_to_argv_array(char *arg, struct strvec *); 65 66 int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); 67 size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
+2 -2
refs.h
··· 145 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add 146 * the results to 'prefixes' 147 */ 148 - struct argv_array; 149 - void expand_ref_prefix(struct argv_array *prefixes, const char *prefix); 150 151 int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref); 152 int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
··· 145 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add 146 * the results to 'prefixes' 147 */ 148 + struct strvec; 149 + void expand_ref_prefix(struct strvec *prefixes, const char *prefix); 150 151 int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref); 152 int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
+2 -2
refspec.h
··· 60 61 int valid_fetch_refspec(const char *refspec); 62 63 - struct argv_array; 64 /* 65 * Determine what <prefix> values to pass to the peer in ref-prefix lines 66 * (see Documentation/technical/protocol-v2.txt). 67 */ 68 void refspec_ref_prefixes(const struct refspec *rs, 69 - struct argv_array *ref_prefixes); 70 71 #endif /* REFSPEC_H */
··· 60 61 int valid_fetch_refspec(const char *refspec); 62 63 + struct strvec; 64 /* 65 * Determine what <prefix> values to pass to the peer in ref-prefix lines 66 * (see Documentation/technical/protocol-v2.txt). 67 */ 68 void refspec_ref_prefixes(const struct refspec *rs, 69 + struct strvec *ref_prefixes); 70 71 #endif /* REFSPEC_H */
+2 -2
remote.h
··· 168 169 struct oid_array; 170 struct packet_reader; 171 - struct argv_array; 172 struct string_list; 173 struct ref **get_remote_heads(struct packet_reader *reader, 174 struct ref **list, unsigned int flags, ··· 178 /* Used for protocol v2 in order to retrieve refs from a remote */ 179 struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, 180 struct ref **list, int for_push, 181 - const struct argv_array *ref_prefixes, 182 const struct string_list *server_options, 183 int stateless_rpc); 184
··· 168 169 struct oid_array; 170 struct packet_reader; 171 + struct strvec; 172 struct string_list; 173 struct ref **get_remote_heads(struct packet_reader *reader, 174 struct ref **list, unsigned int flags, ··· 178 /* Used for protocol v2 in order to retrieve refs from a remote */ 179 struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, 180 struct ref **list, int for_push, 181 + const struct strvec *ref_prefixes, 182 const struct string_list *server_options, 183 int stateless_rpc); 184
+2 -2
serve.h
··· 1 #ifndef SERVE_H 2 #define SERVE_H 3 4 - struct argv_array; 5 - int has_capability(const struct argv_array *keys, const char *capability, 6 const char **value); 7 8 struct serve_options {
··· 1 #ifndef SERVE_H 2 #define SERVE_H 3 4 + struct strvec; 5 + int has_capability(const struct strvec *keys, const char *capability, 6 const char **value); 7 8 struct serve_options {
+3 -3
submodule.h
··· 1 #ifndef SUBMODULE_H 2 #define SUBMODULE_H 3 4 - struct argv_array; 5 struct cache_entry; 6 struct diff_options; 7 struct index_state; ··· 84 const struct submodule *submodule_from_ce(const struct cache_entry *ce); 85 void check_for_new_submodule_commits(struct object_id *oid); 86 int fetch_populated_submodules(struct repository *r, 87 - const struct argv_array *options, 88 const char *prefix, 89 int command_line_option, 90 int default_option, ··· 143 * a submodule by clearing any repo-specific environment variables, but 144 * retaining any config in the environment. 145 */ 146 - void prepare_submodule_repo_env(struct argv_array *out); 147 148 #define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0) 149 void absorb_git_dir_into_superproject(const char *path,
··· 1 #ifndef SUBMODULE_H 2 #define SUBMODULE_H 3 4 + struct strvec; 5 struct cache_entry; 6 struct diff_options; 7 struct index_state; ··· 84 const struct submodule *submodule_from_ce(const struct cache_entry *ce); 85 void check_for_new_submodule_commits(struct object_id *oid); 86 int fetch_populated_submodules(struct repository *r, 87 + const struct strvec *options, 88 const char *prefix, 89 int command_line_option, 90 int default_option, ··· 143 * a submodule by clearing any repo-specific environment variables, but 144 * retaining any config in the environment. 145 */ 146 + void prepare_submodule_repo_env(struct strvec *out); 147 148 #define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0) 149 void absorb_git_dir_into_superproject(const char *path,
+1 -1
transport-internal.h
··· 3 4 struct ref; 5 struct transport; 6 - struct argv_array; 7 8 struct transport_vtable { 9 /**
··· 3 4 struct ref; 5 struct transport; 6 + struct strvec; 7 8 struct transport_vtable { 9 /**
+2 -2
upload-pack.h
··· 11 void upload_pack(struct upload_pack_options *options); 12 13 struct repository; 14 - struct argv_array; 15 struct packet_reader; 16 - int upload_pack_v2(struct repository *r, struct argv_array *keys, 17 struct packet_reader *request); 18 19 struct strbuf;
··· 11 void upload_pack(struct upload_pack_options *options); 12 13 struct repository; 14 + struct strvec; 15 struct packet_reader; 16 + int upload_pack_v2(struct repository *r, struct strvec *keys, 17 struct packet_reader *request); 18 19 struct strbuf;