From: Junio C Hamano Date: Sat, 13 May 2006 21:10:48 +0000 (-0700) Subject: Merge branch 'lt/fix-config' into lt/config X-Git-Tag: v1.4.1-rc1~116^2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/8d48ad62a902556b523ee892a3fbe4206d576d3f?ds=inline;hp=-c Merge branch 'lt/fix-config' into lt/config * lt/fix-config: git config syntax updates Another config file parsing fix. checkout: use --aggressive when running a 3-way merge (-m). Fix git-pack-objects for 64-bit platforms with manual adjustment of t/t1300 for "git repo-config --list" option. Signed-off-by: Junio C Hamano --- 8d48ad62a902556b523ee892a3fbe4206d576d3f diff --combined pack-objects.c index 523a1c7da8,a81d609b26..1b9e7a1cb9 --- a/pack-objects.c +++ b/pack-objects.c @@@ -156,7 -156,7 +156,7 @@@ static void prepare_pack_revindex(struc rix->revindex = xmalloc(sizeof(unsigned long) * (num_ent + 1)); for (i = 0; i < num_ent; i++) { - long hl = *((long *)(index + 24 * i)); + uint32_t hl = *((uint32_t *)(index + 24 * i)); rix->revindex[i] = ntohl(hl); } /* This knows the pack format -- the 20-byte trailer @@@ -994,7 -994,6 +994,7 @@@ static int type_size_sort(const struct struct unpacked { struct object_entry *entry; void *data; + struct delta_index *index; }; /* @@@ -1005,56 -1004,64 +1005,56 @@@ * more importantly, the bigger file is likely the more recent * one. */ -static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_depth) +static int try_delta(struct unpacked *trg, struct unpacked *src, + struct delta_index *src_index, unsigned max_depth) { - struct object_entry *cur_entry = cur->entry; - struct object_entry *old_entry = old->entry; - unsigned long size, oldsize, delta_size, sizediff; - long max_size; + struct object_entry *trg_entry = trg->entry; + struct object_entry *src_entry = src->entry; + unsigned long size, src_size, delta_size, sizediff, max_size; void *delta_buf; /* Don't bother doing diffs between different types */ - if (cur_entry->type != old_entry->type) + if (trg_entry->type != src_entry->type) return -1; /* We do not compute delta to *create* objects we are not * going to pack. */ - if (cur_entry->preferred_base) + if (trg_entry->preferred_base) return -1; - /* If the current object is at pack edge, take the depth the + /* + * If the current object is at pack edge, take the depth the * objects that depend on the current object into account -- * otherwise they would become too deep. */ - if (cur_entry->delta_child) { - if (max_depth <= cur_entry->delta_limit) + if (trg_entry->delta_child) { + if (max_depth <= trg_entry->delta_limit) return 0; - max_depth -= cur_entry->delta_limit; + max_depth -= trg_entry->delta_limit; } - - size = cur_entry->size; - oldsize = old_entry->size; - sizediff = oldsize > size ? oldsize - size : size - oldsize; - - if (size < 50) - return -1; - if (old_entry->depth >= max_depth) + if (src_entry->depth >= max_depth) return 0; - /* - * NOTE! - * - * We always delta from the bigger to the smaller, since that's - * more space-efficient (deletes don't have to say _what_ they - * delete). - */ + /* Now some size filtering euristics. */ + size = trg_entry->size; max_size = size / 2 - 20; - if (cur_entry->delta) - max_size = cur_entry->delta_size-1; + if (trg_entry->delta) + max_size = trg_entry->delta_size-1; + src_size = src_entry->size; + sizediff = src_size < size ? size - src_size : 0; if (sizediff >= max_size) return 0; - delta_buf = diff_delta(old->data, oldsize, - cur->data, size, &delta_size, max_size); + + delta_buf = create_delta(src_index, trg->data, size, &delta_size, max_size); if (!delta_buf) return 0; - cur_entry->delta = old_entry; - cur_entry->delta_size = delta_size; - cur_entry->depth = old_entry->depth + 1; + + trg_entry->delta = src_entry; + trg_entry->delta_size = delta_size; + trg_entry->depth = src_entry->depth + 1; free(delta_buf); - return 0; + return 1; } static void progress_interval(int signum) @@@ -1102,19 -1109,11 +1102,19 @@@ static void find_deltas(struct object_e */ continue; + if (entry->size < 50) + continue; + if (n->index) + free_delta_index(n->index); free(n->data); n->entry = entry; n->data = read_sha1_file(entry->sha1, type, &size); if (size != entry->size) - die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(entry->sha1), size, entry->size); + die("object %s inconsistent object length (%lu vs %lu)", + sha1_to_hex(entry->sha1), size, entry->size); + n->index = create_delta_index(n->data, size); + if (!n->index) + die("out of memory"); j = window; while (--j > 0) { @@@ -1125,7 -1124,7 +1125,7 @@@ m = array + other_idx; if (!m->entry) break; - if (try_delta(n, m, depth) < 0) + if (try_delta(n, m, m->index, depth) < 0) break; } #if 0 @@@ -1145,11 -1144,8 +1145,11 @@@ if (progress) fputc('\n', stderr); - for (i = 0; i < window; ++i) + for (i = 0; i < window; ++i) { + if (array[i].index) + free_delta_index(array[i].index); free(array[i].data); + } free(array); } @@@ -1243,7 -1239,6 +1243,7 @@@ int main(int argc, char **argv setup_git_directory(); + progress = isatty(2); for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@@ -1274,10 -1269,6 +1274,10 @@@ usage(pack_usage); continue; } + if (!strcmp("--progress", arg)) { + progress = 1; + continue; + } if (!strcmp("-q", arg)) { progress = 0; continue; diff --combined repo-config.c index 63eda1bb78,58b6c5284f..127afd784c --- a/repo-config.c +++ b/repo-config.c @@@ -2,83 -2,60 +2,84 @@@ #include static const char git_config_set_usage[] = -"git-repo-config [ --bool | --int ] [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]"; +"git-repo-config [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --unset | --unset-all] name [value [value_regex]] | --list"; static char* key = NULL; -static char* value = NULL; +static regex_t* key_regexp = NULL; static regex_t* regexp = NULL; +static int show_keys = 0; +static int use_key_regexp = 0; static int do_all = 0; static int do_not_match = 0; static int seen = 0; static enum { T_RAW, T_INT, T_BOOL } type = T_RAW; +static int show_all_config(const char *key_, const char *value_) +{ + if (value_) + printf("%s=%s\n", key_, value_); + else + printf("%s\n", key_); + return 0; +} + static int show_config(const char* key_, const char* value_) { + char value[256]; + const char *vptr = value; + int dup_error = 0; + if (value_ == NULL) value_ = ""; - if (!strcmp(key_, key) && - (regexp == NULL || + if (!use_key_regexp && strcmp(key_, key)) + return 0; + if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0)) + return 0; + if (regexp != NULL && (do_not_match ^ - !regexec(regexp, value_, 0, NULL, 0)))) { - if (do_all) { - printf("%s\n", value_); - return 0; - } - if (seen > 0) { - fprintf(stderr, "More than one value: %s\n", value); - free(value); - } + regexec(regexp, value_, 0, NULL, 0))) + return 0; - if (type == T_INT) { - value = malloc(256); - sprintf(value, "%d", git_config_int(key_, value_)); - } else if (type == T_BOOL) { - value = malloc(256); - sprintf(value, "%s", git_config_bool(key_, value_) - ? "true" : "false"); - } else { - value = strdup(value_); - } - seen++; + if (show_keys) + printf("%s ", key_); + if (seen && !do_all) + dup_error = 1; + if (type == T_INT) + sprintf(value, "%d", git_config_int(key_, value_)); + else if (type == T_BOOL) + vptr = git_config_bool(key_, value_) ? "true" : "false"; + else + vptr = value_; + seen++; + if (dup_error) { + error("More than one value for the key %s: %s", + key_, vptr); } + else + printf("%s\n", vptr); + return 0; } static int get_value(const char* key_, const char* regex_) { -- int i; + char *tl; - key = malloc(strlen(key_)+1); - for (i = 0; key_[i]; i++) - key[i] = tolower(key_[i]); - key[i] = 0; + key = strdup(key_); + for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) + *tl = tolower(*tl); + for (tl=key; *tl && *tl != '.'; ++tl) + *tl = tolower(*tl); + if (use_key_regexp) { + key_regexp = (regex_t*)malloc(sizeof(regex_t)); + if (regcomp(key_regexp, key, REG_EXTENDED)) { + fprintf(stderr, "Invalid key pattern: %s\n", key_); + return -1; + } + } + if (regex_) { if (regex_[0] == '!') { do_not_match = 1; @@@ -92,7 -69,11 +93,7 @@@ } } - i = git_config(show_config); - if (value) { - printf("%s\n", value); - free(value); - } + git_config(show_config); free(key); if (regexp) { regfree(regexp); @@@ -100,9 -81,9 +101,9 @@@ } if (do_all) - return 0; + return !seen; - return seen == 1 ? 0 : 1; + return (seen == 1) ? 0 : 1; } int main(int argc, const char **argv) @@@ -114,8 -95,6 +115,8 @@@ type = T_INT; else if (!strcmp(argv[1], "--bool")) type = T_BOOL; + else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) + return git_config(show_all_config); else break; argc--; @@@ -135,11 -114,6 +136,11 @@@ else if (!strcmp(argv[1], "--get-all")) { do_all = 1; return get_value(argv[2], NULL); + } else if (!strcmp(argv[1], "--get-regexp")) { + show_keys = 1; + use_key_regexp = 1; + do_all = 1; + return get_value(argv[2], NULL); } else return git_config_set(argv[1], argv[2]); @@@ -153,11 -127,6 +154,11 @@@ else if (!strcmp(argv[1], "--get-all")) { do_all = 1; return get_value(argv[2], argv[3]); + } else if (!strcmp(argv[1], "--get-regexp")) { + show_keys = 1; + use_key_regexp = 1; + do_all = 1; + return get_value(argv[2], argv[3]); } else if (!strcmp(argv[1], "--replace-all")) return git_config_set_multivar(argv[2], argv[3], NULL, 1); diff --combined sha1_file.c index b62d0e3dcd,642c45ad75..631a605201 --- a/sha1_file.c +++ b/sha1_file.c @@@ -108,10 -108,9 +108,10 @@@ int safe_create_leading_directories(cha char * sha1_to_hex(const unsigned char *sha1) { - static char buffer[50]; + static int bufno; + static char hexbuffer[4][50]; static const char hex[] = "0123456789abcdef"; - char *buf = buffer; + char *buffer = hexbuffer[3 & ++bufno], *buf = buffer; int i; for (i = 0; i < 20; i++) { @@@ -217,8 -216,6 +217,8 @@@ char *sha1_pack_index_name(const unsign struct alternate_object_database *alt_odb_list; static struct alternate_object_database **alt_odb_tail; +static void read_info_alternates(const char * alternates, int depth); + /* * Prepare alternate object database registry. * @@@ -234,85 -231,14 +234,85 @@@ * SHA1, an extra slash for the first level indirection, and the * terminating NUL. */ -static void link_alt_odb_entries(const char *alt, const char *ep, int sep, - const char *relative_base) +static int link_alt_odb_entry(const char * entry, int len, const char * relative_base, int depth) { - const char *cp, *last; - struct alternate_object_database *ent; + struct stat st; const char *objdir = get_object_directory(); + struct alternate_object_database *ent; + struct alternate_object_database *alt; + /* 43 = 40-byte + 2 '/' + terminating NUL */ + int pfxlen = len; + int entlen = pfxlen + 43; int base_len = -1; + if (*entry != '/' && relative_base) { + /* Relative alt-odb */ + if (base_len < 0) + base_len = strlen(relative_base) + 1; + entlen += base_len; + pfxlen += base_len; + } + ent = xmalloc(sizeof(*ent) + entlen); + + if (*entry != '/' && relative_base) { + memcpy(ent->base, relative_base, base_len - 1); + ent->base[base_len - 1] = '/'; + memcpy(ent->base + base_len, entry, len); + } + else + memcpy(ent->base, entry, pfxlen); + + ent->name = ent->base + pfxlen + 1; + ent->base[pfxlen + 3] = '/'; + ent->base[pfxlen] = ent->base[entlen-1] = 0; + + /* Detect cases where alternate disappeared */ + if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) { + error("object directory %s does not exist; " + "check .git/objects/info/alternates.", + ent->base); + free(ent); + return -1; + } + + /* Prevent the common mistake of listing the same + * thing twice, or object directory itself. + */ + for (alt = alt_odb_list; alt; alt = alt->next) { + if (!memcmp(ent->base, alt->base, pfxlen)) { + free(ent); + return -1; + } + } + if (!memcmp(ent->base, objdir, pfxlen)) { + free(ent); + return -1; + } + + /* add the alternate entry */ + *alt_odb_tail = ent; + alt_odb_tail = &(ent->next); + ent->next = NULL; + + /* recursively add alternates */ + read_info_alternates(ent->base, depth + 1); + + ent->base[pfxlen] = '/'; + + return 0; +} + +static void link_alt_odb_entries(const char *alt, const char *ep, int sep, + const char *relative_base, int depth) +{ + const char *cp, *last; + + if (depth > 5) { + error("%s: ignoring alternate object stores, nesting too deep.", + relative_base); + return; + } + last = alt; while (last < ep) { cp = last; @@@ -322,15 -248,60 +322,15 @@@ last = cp + 1; continue; } - for ( ; cp < ep && *cp != sep; cp++) - ; + while (cp < ep && *cp != sep) + cp++; if (last != cp) { - struct stat st; - struct alternate_object_database *alt; - /* 43 = 40-byte + 2 '/' + terminating NUL */ - int pfxlen = cp - last; - int entlen = pfxlen + 43; - - if (*last != '/' && relative_base) { - /* Relative alt-odb */ - if (base_len < 0) - base_len = strlen(relative_base) + 1; - entlen += base_len; - pfxlen += base_len; - } - ent = xmalloc(sizeof(*ent) + entlen); - - if (*last != '/' && relative_base) { - memcpy(ent->base, relative_base, base_len - 1); - ent->base[base_len - 1] = '/'; - memcpy(ent->base + base_len, - last, cp - last); - } - else - memcpy(ent->base, last, pfxlen); - - ent->name = ent->base + pfxlen + 1; - ent->base[pfxlen + 3] = '/'; - ent->base[pfxlen] = ent->base[entlen-1] = 0; - - /* Detect cases where alternate disappeared */ - if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) { - error("object directory %s does not exist; " - "check .git/objects/info/alternates.", - ent->base); - goto bad; - } - ent->base[pfxlen] = '/'; - - /* Prevent the common mistake of listing the same - * thing twice, or object directory itself. - */ - for (alt = alt_odb_list; alt; alt = alt->next) - if (!memcmp(ent->base, alt->base, pfxlen)) - goto bad; - if (!memcmp(ent->base, objdir, pfxlen)) { - bad: - free(ent); - } - else { - *alt_odb_tail = ent; - alt_odb_tail = &(ent->next); - ent->next = NULL; + if ((*last != '/') && depth) { + error("%s: ignoring relative alternate object store %s", + relative_base, last); + } else { + link_alt_odb_entry(last, cp - last, + relative_base, depth); } } while (cp < ep && *cp == sep) @@@ -339,14 -310,23 +339,14 @@@ } } -void prepare_alt_odb(void) +static void read_info_alternates(const char * relative_base, int depth) { - char path[PATH_MAX]; char *map; - int fd; struct stat st; - char *alt; - - alt = getenv(ALTERNATE_DB_ENVIRONMENT); - if (!alt) alt = ""; - - if (alt_odb_tail) - return; - alt_odb_tail = &alt_odb_list; - link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL); + char path[PATH_MAX]; + int fd; - sprintf(path, "%s/info/alternates", get_object_directory()); + sprintf(path, "%s/info/alternates", relative_base); fd = open(path, O_RDONLY); if (fd < 0) return; @@@ -359,26 -339,11 +359,26 @@@ if (map == MAP_FAILED) return; - link_alt_odb_entries(map, map + st.st_size, '\n', - get_object_directory()); + link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth); + munmap(map, st.st_size); } +void prepare_alt_odb(void) +{ + char *alt; + + alt = getenv(ALTERNATE_DB_ENVIRONMENT); + if (!alt) alt = ""; + + if (alt_odb_tail) + return; + alt_odb_tail = &alt_odb_list; + link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0); + + read_info_alternates(get_object_directory(), 0); +} + static char *find_sha1_file(const unsigned char *sha1, struct stat *st) { char *name = sha1_file_name(sha1); @@@ -1161,7 -1126,7 +1161,7 @@@ int find_pack_entry_one(const unsigned int mi = (lo + hi) / 2; int cmp = memcmp(index + 24 * mi + 4, sha1, 20); if (!cmp) { - e->offset = ntohl(*((int*)(index + 24 * mi))); + e->offset = ntohl(*((uint32_t *)(index + 24 * mi))); memcpy(e->sha1, sha1, 20); e->p = p; return 1; diff --combined t/t1300-repo-config.sh index 7090ea92c1,028d15956b..8260d57b63 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@@ -229,7 -229,7 +229,7 @@@ test_expect_failure 'invalid key' 'git- test_expect_success 'correct key' 'git-repo-config 123456.a123 987' test_expect_success 'hierarchical section' \ - 'git-repo-config 1.2.3.alpha beta' + 'git-repo-config Version.1.2.3eX.Alpha beta' cat > expect << EOF [beta] ; silly comment # another comment @@@ -241,30 -241,12 +241,30 @@@ noIndent= sillyValue ; 'nother silly co NoNewLine = wow2 for me [123456] a123 = 987 - [1.2.3] - alpha = beta + [Version "1.2.3eX"] + Alpha = beta EOF test_expect_success 'hierarchical section value' 'cmp .git/config expect' +cat > expect << EOF +beta.noindent=sillyValue +nextsection.nonewline=wow2 for me +123456.a123=987 - 1.2.3.alpha=beta ++version.1.2.3eX.alpha=beta +EOF + +test_expect_success 'working --list' \ + 'git-repo-config --list > output && cmp output expect' + +cat > expect << EOF +beta.noindent sillyValue +nextsection.nonewline wow2 for me +EOF + +test_expect_success '--get-regexp' \ + 'git-repo-config --get-regexp in > output && cmp output expect' + cat > .git/config << EOF [novalue] variable @@@ -273,41 -255,5 +273,41 @@@ EO test_expect_success 'get variable with no value' \ 'git-repo-config --get novalue.variable ^$' +git-repo-config > output 2>&1 + +test_expect_success 'no arguments, but no crash' \ + "test $? = 129 && grep usage output" + +cat > .git/config << EOF +[a.b] + c = d +EOF + +git-repo-config a.x y + +cat > expect << EOF +[a.b] + c = d +[a] + x = y +EOF + +test_expect_success 'new section is partial match of another' 'cmp .git/config expect' + +git-repo-config b.x y +git-repo-config a.b c + +cat > expect << EOF +[a.b] + c = d +[a] + x = y + b = c +[b] + x = y +EOF + +test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect' + test_done