From: Junio C Hamano Date: Sun, 27 Aug 2017 06:01:41 +0000 (-0700) Subject: Sync with master X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f28d330327670643ea4cc6f8feceac4024df00a0?hp=238e487ea943f80734cc6dad665e7238b8cbc7ff Sync with master * master: The fifth batch post 2.14 --- diff --git a/.tsan-suppressions b/.tsan-suppressions new file mode 100644 index 0000000000..8c85014a0a --- /dev/null +++ b/.tsan-suppressions @@ -0,0 +1,10 @@ +# Suppressions for ThreadSanitizer (tsan). +# +# This file is used by setting the environment variable TSAN_OPTIONS to, e.g., +# "suppressions=$(pwd)/.tsan-suppressions". Observe that relative paths such as +# ".tsan-suppressions" might not work. + +# A static variable is written to racily, but we always write the same value, so +# in practice it (hopefully!) doesn't matter. +race:^want_color$ +race:^transfer_debug$ diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 631cbd840a..4ebc3d3271 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -66,7 +66,7 @@ OPTIONS disables it is in effect), make sure the patch is applicable to what the current index file records. If the file to be patched in the working tree is not - up-to-date, it is flagged as an error. This flag also + up to date, it is flagged as an error. This flag also causes the index file to be updated. --cached:: @@ -259,7 +259,7 @@ treats these changes as follows. If `--index` is specified (explicitly or implicitly), then the submodule commits must match the index exactly for the patch to apply. If any of the submodules are checked-out, then these check-outs are completely -ignored, i.e., they are not required to be up-to-date or clean and they +ignored, i.e., they are not required to be up to date or clean and they are not updated. If `--index` is not specified, then the submodule commits in the patch diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index d0b3358771..e292737b9c 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -195,10 +195,8 @@ start-point is either a local or remote-tracking branch. branch.autoSetupMerge configuration variable is true. --set-upstream:: - If specified branch does not exist yet or if `--force` has been - given, acts exactly like `--track`. Otherwise sets up configuration - like `--track` would when creating the branch, except that where - branch points to is not changed. + As this option had confusing syntax, it is no longer supported. + Please use `--track` or `--set-upstream-to` instead. -u :: --set-upstream-to=:: diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index a336ae5f6f..ba90066f10 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -223,7 +223,7 @@ access method and requested operation. That means that even if you offer only read access (e.g. by using the pserver method), 'git-cvsserver' should have write access to the database to work reliably (otherwise you need to make sure -that the database is up-to-date any time 'git-cvsserver' is executed). +that the database is up to date any time 'git-cvsserver' is executed). By default it uses SQLite databases in the Git directory, named `gitcvs..sqlite`. Note that the SQLite backend creates diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index a171506952..b380677718 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -85,7 +85,7 @@ a 'git write-tree' + 'git diff-tree'. Thus that's the default mode. The non-cached version asks the question: show me the differences between HEAD and the currently checked out - tree - index contents _and_ files that aren't up-to-date + tree - index contents _and_ files that aren't up to date which is obviously a very useful question too, since that tells you what you *could* commit. Again, the output matches the 'git diff-tree -r' @@ -100,8 +100,8 @@ have not actually done a 'git update-index' on it yet - there is no torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD :100644 100664 7476bb... 000000... kernel/sched.c -i.e., it shows that the tree has changed, and that `kernel/sched.c` has is -not up-to-date and may contain new stuff. The all-zero sha1 means that to +i.e., it shows that the tree has changed, and that `kernel/sched.c` is +not up to date and may contain new stuff. The all-zero sha1 means that to get the real diff, you need to look at the object in the working directory directly rather than do an object-to-object diff. diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 615e6bacde..4df6431c34 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -141,7 +141,7 @@ exception is when the changed index entries are in the state that would result from the merge already.) If all named commits are already ancestors of `HEAD`, 'git merge' -will exit early with the message "Already up-to-date." +will exit early with the message "Already up to date." FAST-FORWARD MERGE ------------------ diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 4f6bed61a9..6805a74aec 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -334,7 +334,7 @@ which makes little sense. -f:: --force-rebase:: - Force a rebase even if the current branch is up-to-date and + Force a rebase even if the current branch is up to date and the command without `--force` would return without doing anything. + You may find this (or --no-ff with an interactive rebase) helpful after diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt index 9ee083c415..031f31fa47 100644 --- a/Documentation/git-rerere.txt +++ b/Documentation/git-rerere.txt @@ -205,7 +205,7 @@ development on the topic branch: ------------ you could run `git rebase master topic`, to bring yourself -up-to-date before your topic is ready to be sent upstream. +up to date before your topic is ready to be sent upstream. This would result in falling back to a three-way merge, and it would conflict the same way as the test merge you resolved earlier. 'git rerere' will be run by 'git rebase' to help you resolve this diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index 683e591330..b5c46223c4 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -146,7 +146,7 @@ the submodule's history. If it exists the submodule. section in the linkgit:gitmodules[5] file will also be removed and that file will be staged (unless --cached or -n are used). -A submodule is considered up-to-date when the HEAD is the same as +A submodule is considered up to date when the HEAD is the same as recorded in the index, no tracked files are modified and no untracked files that aren't ignored are present in the submodules work tree. Ignored files are deemed expendable and won't stop a submodule's work diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index aa2aeabb60..636e09048e 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -424,7 +424,7 @@ Any other arguments are passed directly to 'git log' 'set-tree':: You should consider using 'dcommit' instead of this command. Commit specified commit or tree objects to SVN. This relies on - your imported fetch data being up-to-date. This makes + your imported fetch data being up to date. This makes absolutely no attempts to do patching when committing to SVN, it simply overwrites files with those specified in the tree or commit. All merging is assumed to have taken place diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index 1579abf3c3..e19eba62cd 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -214,7 +214,7 @@ will remove the intended effect of the option. Using --refresh --------------- `--refresh` does not calculate a new sha1 file or bring the index -up-to-date for mode/content changes. But what it *does* do is to +up to date for mode/content changes. But what it *does* do is to "re-match" the stat information of a file with the index, so that you can refresh the index for a file that hasn't been changed but where the stat entry is out of date. diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt index 7577f27ec2..e29a9effcc 100644 --- a/Documentation/gitcore-tutorial.txt +++ b/Documentation/gitcore-tutorial.txt @@ -631,7 +631,7 @@ So after you do a `cp -a` to create a new copy, you'll want to do $ git update-index --refresh ---------------- + -in the new repository to make sure that the index file is up-to-date. +in the new repository to make sure that the index file is up to date. Note that the second point is true even across machines. You can duplicate a remote Git repository with *any* regular copy mechanism, be it @@ -701,7 +701,7 @@ $ git checkout-index -u -a ---------------- where the `-u` flag means that you want the checkout to keep the index -up-to-date (so that you don't have to refresh it afterward), and the +up to date (so that you don't have to refresh it afterward), and the `-a` flag means "check out all files" (if you have a stale copy or an older version of a checked out tree you may also need to add the `-f` flag first, to tell 'git checkout-index' to *force* overwriting of any old @@ -1283,7 +1283,7 @@ run a single command, 'git-receive-pack'. First, you need to create an empty repository on the remote machine that will house your public repository. This empty -repository will be populated and be kept up-to-date by pushing +repository will be populated and be kept up to date by pushing into it later. Obviously, this repository creation needs to be done only once. @@ -1450,7 +1450,7 @@ transport protocols (HTTP), you need to keep this repository would contain a call to 'git update-server-info' but you need to manually enable the hook with `mv post-update.sample post-update`. This makes sure -'git update-server-info' keeps the necessary files up-to-date. +'git update-server-info' keeps the necessary files up to date. 3. Push into the public repository from your primary repository. diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 623ed1a138..1bb4f92d4d 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -369,7 +369,7 @@ them. When enabled, the default 'post-update' hook runs 'git update-server-info' to keep the information used by dumb -transports (e.g., HTTP) up-to-date. If you are publishing +transports (e.g., HTTP) up to date. If you are publishing a Git repository that is accessible via HTTP, you should probably enable this hook. diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt index f51ed4e37c..adf9554ad2 100644 --- a/Documentation/gitrepository-layout.txt +++ b/Documentation/gitrepository-layout.txt @@ -71,7 +71,7 @@ objects/info/packs:: This file is to help dumb transports discover what packs are available in this object store. Whenever a pack is added or removed, `git update-server-info` should be run - to keep this file up-to-date if the repository is + to keep this file up to date if the repository is published for dumb transports. 'git repack' does this by default. diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt index 794b83393e..242de31cb6 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.txt @@ -109,7 +109,7 @@ summary of the situation with 'git status': $ git status On branch master Changes to be committed: -Your branch is up-to-date with 'origin/master'. +Your branch is up to date with 'origin/master'. (use "git reset HEAD ..." to unstage) modified: file1 diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 5b4a62e936..4e32304301 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -39,7 +39,7 @@ set to `no` at the beginning of them. --ff-only:: Refuse to merge and exit with a non-zero status unless the - current `HEAD` is already up-to-date or the merge can be + current `HEAD` is already up to date or the merge can be resolved as a fast-forward. --log[=]:: diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index a34917153f..ed1eae8b83 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -199,7 +199,7 @@ After reference and capabilities discovery, the client can decide to terminate the connection by sending a flush-pkt, telling the server it can now gracefully terminate, and disconnect, when it does not need any pack data. This can happen with the ls-remote command, and also can happen when -the client already is up-to-date. +the client already is up to date. Otherwise, it enters the negotiation phase, where the client and server determine what the minimal packfile necessary for transport is, diff --git a/Documentation/technical/trivial-merge.txt b/Documentation/technical/trivial-merge.txt index c79d4a7c47..1f1c33d0da 100644 --- a/Documentation/technical/trivial-merge.txt +++ b/Documentation/technical/trivial-merge.txt @@ -32,7 +32,7 @@ or the result. If multiple cases apply, the one used is listed first. A result which changes the index is an error if the index is not empty -and not up-to-date. +and not up to date. Entries marked '+' have stat information. Spaces marked '*' don't affect the result. @@ -65,7 +65,7 @@ empty, no entry is left for that stage). Otherwise, the given entry is left in stage 0, and there are no other entries. A result of "no merge" is an error if the index is not empty and not -up-to-date. +up to date. *empty* means that the tree must not have a directory-file conflict with the entry. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index bc29298678..b4d88af133 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -2044,10 +2044,12 @@ If a push would not result in a <> of the remote branch, then it will fail with an error like: ------------------------------------------------- -error: remote 'refs/heads/master' is not an ancestor of - local 'refs/heads/master'. - Maybe you are not up-to-date and need to pull first? -error: failed to push to 'ssh://yourserver.com/~you/proj.git' + ! [rejected] master -> master (non-fast-forward) +error: failed to push some refs to '...' +hint: Updates were rejected because the tip of your current branch is behind +hint: its remote counterpart. Integrate the remote changes (e.g. +hint: 'git pull ...') before pushing again. +hint: See the 'Note about fast-forwards' in 'git push --help' for details. ------------------------------------------------- This can happen, for example, if you: @@ -2193,7 +2195,7 @@ $ cd work Linus's tree will be stored in the remote-tracking branch named origin/master, and can be updated using linkgit:git-fetch[1]; you can track other public trees using linkgit:git-remote[1] to set up a "remote" and -linkgit:git-fetch[1] to keep them up-to-date; see +linkgit:git-fetch[1] to keep them up to date; see <>. Now create the branches in which you are going to work; these start out diff --git a/Makefile b/Makefile index f2bb7f2f63..68948dfbf3 100644 --- a/Makefile +++ b/Makefile @@ -162,6 +162,11 @@ all:: # algorithm. This is slower, but may detect attempted collision attacks. # Takes priority over other *_SHA1 knobs. # +# Define DC_SHA1_EXTERNAL in addition to DC_SHA1 if you want to build / link +# git with the external SHA1 collision-detect library. +# Without this option, i.e. the default behavior is to build git with its +# own built-in code (or submodule). +# # Define DC_SHA1_SUBMODULE in addition to DC_SHA1 to use the # sha1collisiondetection shipped as a submodule instead of the # non-submodule copy in sha1dc/. This is an experimental option used @@ -1475,6 +1480,15 @@ ifdef APPLE_COMMON_CRYPTO BASIC_CFLAGS += -DSHA1_APPLE else DC_SHA1 := YesPlease + BASIC_CFLAGS += -DSHA1_DC + LIB_OBJS += sha1dc_git.o +ifdef DC_SHA1_EXTERNAL + ifdef DC_SHA1_SUBMODULE +$(error Only set DC_SHA1_EXTERNAL or DC_SHA1_SUBMODULE, not both) + endif + BASIC_CFLAGS += -DDC_SHA1_EXTERNAL + EXTLIBS += -lsha1detectcoll +else ifdef DC_SHA1_SUBMODULE LIB_OBJS += sha1collisiondetection/lib/sha1.o LIB_OBJS += sha1collisiondetection/lib/ubc_check.o @@ -1484,17 +1498,15 @@ else LIB_OBJS += sha1dc/ubc_check.o endif BASIC_CFLAGS += \ - -DSHA1_DC \ -DSHA1DC_NO_STANDARD_INCLUDES \ -DSHA1DC_INIT_SAFE_HASH_DEFAULT=0 \ -DSHA1DC_CUSTOM_INCLUDE_SHA1_C="\"cache.h\"" \ - -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C="\"sha1dc_git.c\"" \ - -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H="\"sha1dc_git.h\"" \ -DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="\"git-compat-util.h\"" endif endif endif endif +endif ifdef SHA1_MAX_BLOCK_SIZE LIB_OBJS += compat/sha1-chunked.o diff --git a/apply.c b/apply.c index 86666217d4..71cbbd141c 100644 --- a/apply.c +++ b/apply.c @@ -812,16 +812,13 @@ static int has_epoch_timestamp(const char *nameline) * 1970-01-01, and the seconds part must be "00". */ const char stamp_regexp[] = - "^(1969-12-31|1970-01-01)" - " " - "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?" + "^[0-2][0-9]:([0-5][0-9]):00(\\.0+)?" " " "([-+][0-2][0-9]:?[0-5][0-9])\n"; const char *timestamp = NULL, *cp, *colon; static regex_t *stamp; regmatch_t m[10]; - int zoneoffset; - int hourminute; + int zoneoffset, epoch_hour, hour, minute; int status; for (cp = nameline; *cp != '\n'; cp++) { @@ -830,6 +827,18 @@ static int has_epoch_timestamp(const char *nameline) } if (!timestamp) return 0; + + /* + * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31 + * (west of GMT) or 1970-01-01 (east of GMT) + */ + if (skip_prefix(timestamp, "1969-12-31 ", ×tamp)) + epoch_hour = 24; + else if (skip_prefix(timestamp, "1970-01-01 ", ×tamp)) + epoch_hour = 0; + else + return 0; + if (!stamp) { stamp = xmalloc(sizeof(*stamp)); if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) { @@ -847,6 +856,9 @@ static int has_epoch_timestamp(const char *nameline) return 0; } + hour = strtol(timestamp, NULL, 10); + minute = strtol(timestamp + m[1].rm_so, NULL, 10); + zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10); if (*colon == ':') zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10); @@ -855,20 +867,7 @@ static int has_epoch_timestamp(const char *nameline) if (timestamp[m[3].rm_so] == '-') zoneoffset = -zoneoffset; - /* - * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31 - * (west of GMT) or 1970-01-01 (east of GMT) - */ - if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) || - (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10))) - return 0; - - hourminute = (strtol(timestamp + 11, NULL, 10) * 60 + - strtol(timestamp + 14, NULL, 10) - - zoneoffset); - - return ((zoneoffset < 0 && hourminute == 1440) || - (0 <= zoneoffset && !hourminute)); + return hour * 60 + minute - zoneoffset == epoch_hour * 60; } /* diff --git a/archive.c b/archive.c index 557dd2db85..1ab8d3a1d7 100644 --- a/archive.c +++ b/archive.c @@ -103,17 +103,39 @@ struct archiver_context { struct directory *bottom; }; +static const struct attr_check *get_archive_attrs(const char *path) +{ + static struct attr_check *check; + if (!check) + check = attr_check_initl("export-ignore", "export-subst", NULL); + return git_check_attr(path, check) ? NULL : check; +} + +static int check_attr_export_ignore(const struct attr_check *check) +{ + return check && ATTR_TRUE(check->items[0].value); +} + +static int check_attr_export_subst(const struct attr_check *check) +{ + return check && ATTR_TRUE(check->items[1].value); +} + +static int should_queue_directories(const struct archiver_args *args) +{ + return args->pathspec.has_wildcard; +} + static int write_archive_entry(const unsigned char *sha1, const char *base, int baselen, const char *filename, unsigned mode, int stage, void *context) { static struct strbuf path = STRBUF_INIT; - static struct attr_check *check; struct archiver_context *c = context; struct archiver_args *args = c->args; write_archive_entry_fn_t write_entry = c->write_entry; - const char *path_without_prefix; int err; + const char *path_without_prefix; args->convert = 0; strbuf_reset(&path); @@ -125,12 +147,12 @@ static int write_archive_entry(const unsigned char *sha1, const char *base, strbuf_addch(&path, '/'); path_without_prefix = path.buf + args->baselen; - if (!check) - check = attr_check_initl("export-ignore", "export-subst", NULL); - if (!git_check_attr(path_without_prefix, check)) { - if (ATTR_TRUE(check->items[0].value)) + if (!S_ISDIR(mode) || !should_queue_directories(args)) { + const struct attr_check *check; + check = get_archive_attrs(path_without_prefix); + if (check_attr_export_ignore(check)) return 0; - args->convert = ATTR_TRUE(check->items[1].value); + args->convert = check_attr_export_subst(check); } if (S_ISDIR(mode) || S_ISGITLINK(mode)) { @@ -204,6 +226,17 @@ static int queue_or_write_archive_entry(const unsigned char *sha1, } if (S_ISDIR(mode)) { + size_t baselen = base->len; + const struct attr_check *check; + + /* Borrow base, but restore its original value when done. */ + strbuf_addstr(base, filename); + strbuf_addch(base, '/'); + check = get_archive_attrs(base->buf); + strbuf_setlen(base, baselen); + + if (check_attr_export_ignore(check)) + return 0; queue_directory(sha1, base, filename, mode, stage, c); return READ_TREE_RECURSIVE; @@ -257,7 +290,7 @@ int write_archive_entries(struct archiver_args *args, } err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, - args->pathspec.has_wildcard ? + should_queue_directories(args) ? queue_or_write_archive_entry : write_archive_entry_buf, &context); diff --git a/branch.c b/branch.c index 36541d05cd..703ded69ca 100644 --- a/branch.c +++ b/branch.c @@ -90,24 +90,24 @@ int install_branch_config(int flag, const char *local, const char *origin, const if (shortname) { if (origin) printf_ln(rebasing ? - _("Branch %s set up to track remote branch %s from %s by rebasing.") : - _("Branch %s set up to track remote branch %s from %s."), + _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") : + _("Branch '%s' set up to track remote branch '%s' from '%s'."), local, shortname, origin); else printf_ln(rebasing ? - _("Branch %s set up to track local branch %s by rebasing.") : - _("Branch %s set up to track local branch %s."), + _("Branch '%s' set up to track local branch '%s' by rebasing.") : + _("Branch '%s' set up to track local branch '%s'."), local, shortname); } else { if (origin) printf_ln(rebasing ? - _("Branch %s set up to track remote ref %s by rebasing.") : - _("Branch %s set up to track remote ref %s."), + _("Branch '%s' set up to track remote ref '%s' by rebasing.") : + _("Branch '%s' set up to track remote ref '%s'."), local, remote); else printf_ln(rebasing ? - _("Branch %s set up to track local ref %s by rebasing.") : - _("Branch %s set up to track local ref %s."), + _("Branch '%s' set up to track local ref '%s' by rebasing.") : + _("Branch '%s' set up to track local ref '%s'."), local, remote); } } @@ -357,8 +357,9 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref, if (worktrees[i]->is_detached) continue; - if (worktrees[i]->head_ref && - strcmp(oldref, worktrees[i]->head_ref)) + if (!worktrees[i]->head_ref) + continue; + if (strcmp(oldref, worktrees[i]->head_ref)) continue; refs = get_worktree_ref_store(worktrees[i]); diff --git a/builtin/blame.c b/builtin/blame.c index e0daf17548..67adaef4d8 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -488,7 +488,7 @@ static int read_ancestry(const char *graft_file) return -1; while (!strbuf_getwholeline(&buf, fp, '\n')) { /* The format is just "Commit Parent1 Parent2 ...\n" */ - struct commit_graft *graft = read_graft_line(buf.buf, buf.len); + struct commit_graft *graft = read_graft_line(&buf); if (graft) register_commit_graft(graft, 0); } diff --git a/builtin/branch.c b/builtin/branch.c index 16d391b407..355f9ef5da 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -561,8 +561,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT__QUIET(&quiet, N_("suppress informational messages")), OPT_SET_INT('t', "track", &track, N_("set up tracking mode (see git-pull(1))"), BRANCH_TRACK_EXPLICIT), - OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"), - BRANCH_TRACK_OVERRIDE), + { OPTION_SET_INT, 0, "set-upstream", &track, NULL, N_("do not use"), + PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, BRANCH_TRACK_OVERRIDE }, OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")), OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")), OPT__COLOR(&branch_use_color, N_("use colored output")), @@ -759,8 +759,6 @@ int cmd_branch(int argc, const char **argv, const char *prefix) strbuf_release(&buf); } else if (argc > 0 && argc <= 2) { struct branch *branch = branch_get(argv[0]); - int branch_existed = 0, remote_tracking = 0; - struct strbuf buf = STRBUF_INIT; if (!strcmp(argv[0], "HEAD")) die(_("it does not make sense to create 'HEAD' manually")); @@ -772,28 +770,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix) die(_("-a and -r options to 'git branch' do not make sense with a branch name")); if (track == BRANCH_TRACK_OVERRIDE) - fprintf(stderr, _("The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to\n")); - - strbuf_addf(&buf, "refs/remotes/%s", branch->name); - remote_tracking = ref_exists(buf.buf); - strbuf_release(&buf); + die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead.")); - branch_existed = ref_exists(branch->refname); create_branch(argv[0], (argc == 2) ? argv[1] : head, force, reflog, 0, quiet, track); - /* - * We only show the instructions if the user gave us - * one branch which doesn't exist locally, but is the - * name of a remote-tracking branch. - */ - if (argc == 1 && track == BRANCH_TRACK_OVERRIDE && - !branch_existed && remote_tracking) { - fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name); - fprintf(stderr, " git branch -d %s\n", branch->name); - fprintf(stderr, " git branch --set-upstream-to %s\n", branch->name); - } - } else usage_with_options(builtin_branch_usage, options); diff --git a/builtin/merge.c b/builtin/merge.c index 7df3fe3927..3672e38974 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1359,7 +1359,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * If head can reach all the merge then we are up to date. * but first the most common case of merging one remote. */ - finish_up_to_date(_("Already up-to-date.")); + finish_up_to_date(_("Already up to date.")); goto done; } else if (fast_forward != FF_NO && !remoteheads->next && !common->next && @@ -1442,7 +1442,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) } } if (up_to_date) { - finish_up_to_date(_("Already up-to-date. Yeeah!")); + finish_up_to_date(_("Already up to date. Yeeah!")); goto done; } } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 82ad6e0c81..a57b4f058d 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2171,7 +2171,10 @@ static void *threaded_find_deltas(void *arg) { struct thread_params *me = arg; + progress_lock(); while (me->remaining) { + progress_unlock(); + find_deltas(me->list, &me->remaining, me->window, me->depth, me->processed); @@ -2193,7 +2196,10 @@ static void *threaded_find_deltas(void *arg) pthread_cond_wait(&me->cond, &me->mutex); me->data_ready = 0; pthread_mutex_unlock(&me->mutex); + + progress_lock(); } + progress_unlock(); /* leave ->working 1 so that this doesn't get more work assigned */ return NULL; } diff --git a/color.c b/color.c index 7aa8b076f0..9ccd954d6b 100644 --- a/color.c +++ b/color.c @@ -338,6 +338,13 @@ static int check_auto_color(void) int want_color(int var) { + /* + * NEEDSWORK: This function is sometimes used from multiple threads, and + * we end up using want_auto racily. That "should not matter" since + * we always write the same value, but it's still wrong. This function + * is listed in .tsan-suppressions for the time being. + */ + static int want_auto = -1; if (var < 0) diff --git a/commit.c b/commit.c index 8b28415939..17a93d1e64 100644 --- a/commit.c +++ b/commit.c @@ -134,35 +134,41 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups) return 0; } -struct commit_graft *read_graft_line(char *buf, int len) +struct commit_graft *read_graft_line(struct strbuf *line) { /* The format is just "Commit Parent1 Parent2 ...\n" */ - int i; + int i, phase; + const char *tail = NULL; struct commit_graft *graft = NULL; - const int entry_size = GIT_SHA1_HEXSZ + 1; + struct object_id dummy_oid, *oid; - while (len && isspace(buf[len-1])) - buf[--len] = '\0'; - if (buf[0] == '#' || buf[0] == '\0') + strbuf_rtrim(line); + if (!line->len || line->buf[0] == '#') return NULL; - if ((len + 1) % entry_size) - goto bad_graft_data; - i = (len + 1) / entry_size - 1; - graft = xmalloc(st_add(sizeof(*graft), st_mult(GIT_SHA1_RAWSZ, i))); - graft->nr_parent = i; - if (get_oid_hex(buf, &graft->oid)) - goto bad_graft_data; - for (i = GIT_SHA1_HEXSZ; i < len; i += entry_size) { - if (buf[i] != ' ') - goto bad_graft_data; - if (get_sha1_hex(buf + i + 1, graft->parent[i/entry_size].hash)) + /* + * phase 0 verifies line, counts hashes in line and allocates graft + * phase 1 fills graft + */ + for (phase = 0; phase < 2; phase++) { + oid = graft ? &graft->oid : &dummy_oid; + if (parse_oid_hex(line->buf, oid, &tail)) goto bad_graft_data; + for (i = 0; *tail != '\0'; i++) { + oid = graft ? &graft->parent[i] : &dummy_oid; + if (!isspace(*tail++) || parse_oid_hex(tail, oid, &tail)) + goto bad_graft_data; + } + if (!graft) { + graft = xmalloc(st_add(sizeof(*graft), + st_mult(sizeof(struct object_id), i))); + graft->nr_parent = i; + } } return graft; bad_graft_data: - error("bad graft data: %s", buf); - free(graft); + error("bad graft data: %s", line->buf); + assert(!graft); return NULL; } @@ -174,7 +180,7 @@ static int read_graft_file(const char *graft_file) return -1; while (!strbuf_getwholeline(&buf, fp, '\n')) { /* The format is just "Commit Parent1 Parent2 ...\n" */ - struct commit_graft *graft = read_graft_line(buf.buf, buf.len); + struct commit_graft *graft = read_graft_line(&buf); if (!graft) continue; if (register_commit_graft(graft, 1)) diff --git a/commit.h b/commit.h index 1283d2a51f..6d769590f2 100644 --- a/commit.h +++ b/commit.h @@ -247,7 +247,7 @@ struct commit_graft { }; typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *); -struct commit_graft *read_graft_line(char *buf, int len); +struct commit_graft *read_graft_line(struct strbuf *line); int register_commit_graft(struct commit_graft *, int); struct commit_graft *lookup_commit_graft(const struct object_id *oid); diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh index ee99f1a4ee..932e78dbfe 100755 --- a/contrib/examples/git-merge.sh +++ b/contrib/examples/git-merge.sh @@ -399,7 +399,7 @@ case "$allow_fast_forward,$#,$common,$no_commit" in ?,1,"$1",*) # If head can reach all the merge then we are up to date. # but first the most common case of merging one remote. - finish_up_to_date "Already up-to-date." + finish_up_to_date "Already up to date." exit 0 ;; t,1,"$head",*) @@ -459,7 +459,7 @@ t,1,"$head",*) done if test "$up_to_date" = t then - finish_up_to_date "Already up-to-date. Yeeah!" + finish_up_to_date "Already up to date. Yeeah!" exit 0 fi ;; diff --git a/contrib/examples/git-resolve.sh b/contrib/examples/git-resolve.sh index 70fdc27b72..3099dc851a 100755 --- a/contrib/examples/git-resolve.sh +++ b/contrib/examples/git-resolve.sh @@ -41,7 +41,7 @@ fi case "$common" in "$merge") - echo "Already up-to-date. Yeeah!" + echo "Already up to date. Yeeah!" dropheads exit 0 ;; diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 3c87ebaf57..d05c613c97 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -253,7 +253,7 @@ test_expect_success 'merge the added subproj again, should do nothing' ' # this shouldn not actually do anything, since FETCH_HEAD # is already a parent result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && - check_equal "${result}" "Already up-to-date." + check_equal "${result}" "Already up to date." ) ' diff --git a/convert.c b/convert.c index c5f0b21037..02962261c5 100644 --- a/convert.c +++ b/convert.c @@ -1040,7 +1040,6 @@ static void convert_attrs(struct conv_attrs *ca, const char *path) ca->crlf_action = git_path_check_crlf(ccheck + 4); if (ca->crlf_action == CRLF_UNDEFINED) ca->crlf_action = git_path_check_crlf(ccheck + 0); - ca->attr_action = ca->crlf_action; ca->ident = git_path_check_ident(ccheck + 1); ca->drv = git_path_check_convert(ccheck + 2); if (ca->crlf_action != CRLF_BINARY) { @@ -1054,12 +1053,14 @@ static void convert_attrs(struct conv_attrs *ca, const char *path) else if (eol_attr == EOL_CRLF) ca->crlf_action = CRLF_TEXT_CRLF; } - ca->attr_action = ca->crlf_action; } else { ca->drv = NULL; ca->crlf_action = CRLF_UNDEFINED; ca->ident = 0; } + + /* Save attr and make a decision for action */ + ca->attr_action = ca->crlf_action; if (ca->crlf_action == CRLF_TEXT) ca->crlf_action = text_eol_is_crlf() ? CRLF_TEXT_CRLF : CRLF_TEXT_INPUT; if (ca->crlf_action == CRLF_UNDEFINED && auto_crlf == AUTO_CRLF_FALSE) diff --git a/entry.c b/entry.c index 65458f07a4..cb291aa88b 100644 --- a/entry.c +++ b/entry.c @@ -3,6 +3,7 @@ #include "dir.h" #include "streaming.h" #include "submodule.h" +#include "progress.h" static void create_directories(const char *path, int path_len, const struct checkout *state) @@ -161,16 +162,22 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data) int finish_delayed_checkout(struct checkout *state) { int errs = 0; + unsigned delayed_object_count; + off_t filtered_bytes = 0; struct string_list_item *filter, *path; + struct progress *progress; struct delayed_checkout *dco = state->delayed_checkout; if (!state->delayed_checkout) return errs; dco->state = CE_RETRY; + delayed_object_count = dco->paths.nr; + progress = start_delayed_progress(_("Filtering content"), delayed_object_count); while (dco->filters.nr > 0) { for_each_string_list_item(filter, &dco->filters) { struct string_list available_paths = STRING_LIST_INIT_NODUP; + display_progress(progress, delayed_object_count - dco->paths.nr); if (!async_query_available_blobs(filter->string, &available_paths)) { /* Filter reported an error */ @@ -216,11 +223,17 @@ int finish_delayed_checkout(struct checkout *state) } ce = index_file_exists(state->istate, path->string, strlen(path->string), 0); - errs |= (ce ? checkout_entry(ce, state, NULL) : 1); + if (ce) { + errs |= checkout_entry(ce, state, NULL); + filtered_bytes += ce->ce_stat_data.sd_size; + display_throughput(progress, filtered_bytes); + } else + errs = 1; } } string_list_remove_empty_items(&dco->filters, 0); } + stop_progress(&progress); string_list_clear(&dco->filters, 0); /* At this point we should not have any delayed paths anymore. */ diff --git a/git-gui/po/README b/git-gui/po/README index 0f5837d48e..2514bc22ab 100644 --- a/git-gui/po/README +++ b/git-gui/po/README @@ -165,7 +165,7 @@ to contribute an update. This may be because you would want to improve the translation of existing messages, or because the git-gui software itself was updated and there are new messages that need translation. -In any case, make sure you are up-to-date before starting your work: +In any case, make sure you are up to date before starting your work: $ git checkout master $ git pull diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh index 6c390d6c22..7d19d37951 100755 --- a/git-merge-octopus.sh +++ b/git-merge-octopus.sh @@ -74,7 +74,7 @@ do case "$LF$common$LF" in *"$LF$SHA1$LF"*) - eval_gettextln "Already up-to-date with \$pretty_name" + eval_gettextln "Already up to date with \$pretty_name" continue ;; esac diff --git a/git-p4.py b/git-p4.py index 2fa581789c..76859b453a 100755 --- a/git-p4.py +++ b/git-p4.py @@ -3614,7 +3614,7 @@ def run(self, args): def rebase(self): if os.system("git update-index --refresh") != 0: - die("Some files in your working directory are modified and different than what is in your index. You can use git update-index to bring the index up-to-date or stash away all your changes with git stash."); + die("Some files in your working directory are modified and different than what is in your index. You can use git update-index to bring the index up to date or stash away all your changes with git stash."); if len(read_pipe("git diff-index HEAD --")) > 0: die("You have uncommitted changes. Please commit them before rebasing or stash them away with git stash."); diff --git a/git-send-email.perl b/git-send-email.perl index fa6526986e..2208dcc213 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -155,7 +155,6 @@ sub format_2822_time { } my $have_email_valid = eval { require Email::Valid; 1 }; -my $have_mail_address = eval { require Mail::Address; 1 }; my $smtp; my $auth; my $num_sent = 0; @@ -490,11 +489,7 @@ sub read_config { ($repocommitter) = Git::ident_person(@repo, 'committer'); sub parse_address_line { - if ($have_mail_address) { - return map { $_->format } Mail::Address->parse($_[0]); - } else { - return Git::parse_mailboxes($_[0]); - } + return Git::parse_mailboxes($_[0]); } sub split_addrs { @@ -1089,6 +1084,26 @@ sub sanitize_address { } +sub strip_garbage_one_address { + my ($addr) = @_; + chomp $addr; + if ($addr =~ /^(("[^"]*"|[^"<]*)? *<[^>]*>).*/) { + # "Foo Bar" [possibly garbage here] + # Foo Bar [possibly garbage here] + return $1; + } + if ($addr =~ /^(<[^>]*>).*/) { + # [possibly garbage here] + # if garbage contains other addresses, they are ignored. + return $1; + } + if ($addr =~ /^([^"#,\s]*)/) { + # address without quoting: remove anything after the address + return $1; + } + return $addr; +} + sub sanitize_address_list { return (map { sanitize_address($_) } @_); } @@ -1590,10 +1605,12 @@ sub send_message { # Now parse the message body while(<$fh>) { $message .= $_; - if (/^(Signed-off-by|Cc): ([^>]*>?)/i) { + if (/^(Signed-off-by|Cc): (.*)/i) { chomp; my ($what, $c) = ($1, $2); - chomp $c; + # strip garbage for the address we'll use: + $c = strip_garbage_one_address($c); + # sanitize a bit more to decide whether to suppress the address: my $sc = sanitize_address($c); if ($sc eq $sender) { next if ($suppress_cc{'self'}); diff --git a/hash.h b/hash.h index bef3e630a0..024d0d3d50 100644 --- a/hash.h +++ b/hash.h @@ -8,11 +8,7 @@ #elif defined(SHA1_OPENSSL) #include #elif defined(SHA1_DC) -#ifdef DC_SHA1_SUBMODULE -#include "sha1collisiondetection/lib/sha1.h" -#else -#include "sha1dc/sha1.h" -#endif +#include "sha1dc_git.h" #else /* SHA1_BLK */ #include "block-sha1/sha1.h" #endif diff --git a/merge-recursive.c b/merge-recursive.c index 1494ffdb82..182626c027 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1927,7 +1927,7 @@ int merge_trees(struct merge_options *o, } if (oid_eq(&common->object.oid, &merge->object.oid)) { - output(o, 0, _("Already up-to-date!")); + output(o, 0, _("Already up to date!")); *result = head; return 1; } diff --git a/notes-merge.c b/notes-merge.c index 744c685576..b04d2f2131 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -624,7 +624,7 @@ int notes_merge(struct notes_merge_options *o, if (!oidcmp(&remote->object.oid, base_oid)) { /* Already merged; result == local commit */ if (o->verbosity >= 2) - printf("Already up-to-date!\n"); + printf("Already up to date!\n"); oidcpy(result_oid, &local->object.oid); goto found_result; } diff --git a/notes.c b/notes.c index f090c88363..7f5bfa19c7 100644 --- a/notes.c +++ b/notes.c @@ -64,7 +64,7 @@ struct non_note { #define CLR_PTR_TYPE(ptr) ((void *) ((uintptr_t) (ptr) & ~3)) #define SET_PTR_TYPE(ptr, type) ((void *) ((uintptr_t) (ptr) | (type))) -#define GET_NIBBLE(n, sha1) (((sha1[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f) +#define GET_NIBBLE(n, sha1) ((((sha1)[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f) #define KEY_INDEX (GIT_SHA1_RAWSZ - 1) #define FANOUT_PATH_SEPARATORS ((GIT_SHA1_HEXSZ / 2) - 1) @@ -335,31 +335,20 @@ static void note_tree_free(struct int_node *tree) } /* - * Convert a partial SHA1 hex string to the corresponding partial SHA1 value. - * - hex - Partial SHA1 segment in ASCII hex format - * - hex_len - Length of above segment. Must be multiple of 2 between 0 and 40 - * - sha1 - Partial SHA1 value is written here - * - sha1_len - Max #bytes to store in sha1, Must be >= hex_len / 2, and < 20 - * Returns -1 on error (invalid arguments or invalid SHA1 (not in hex format)). - * Otherwise, returns number of bytes written to sha1 (i.e. hex_len / 2). - * Pads sha1 with NULs up to sha1_len (not included in returned length). + * Read `len` pairs of hexadecimal digits from `hex` and write the + * values to `binary` as `len` bytes. Return 0 on success, or -1 if + * the input does not consist of hex digits). */ -static int get_oid_hex_segment(const char *hex, unsigned int hex_len, - unsigned char *oid, unsigned int oid_len) +static int hex_to_bytes(unsigned char *binary, const char *hex, size_t len) { - unsigned int i, len = hex_len >> 1; - if (hex_len % 2 != 0 || len > oid_len) - return -1; - for (i = 0; i < len; i++) { + for (; len; len--, hex += 2) { unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]); + if (val & ~0xff) return -1; - *oid++ = val; - hex += 2; + *binary++ = val; } - for (; i < oid_len; i++) - *oid++ = 0; - return len; + return 0; } static int non_note_cmp(const struct non_note *a, const struct non_note *b) @@ -417,13 +406,10 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree, struct int_node *node, unsigned int n) { struct object_id object_oid; - unsigned int prefix_len; + size_t prefix_len; void *buf; struct tree_desc desc; struct name_entry entry; - int len, path_len; - unsigned char type; - struct leaf_node *l; buf = fill_tree_descriptor(&desc, &subtree->val_oid); if (!buf) @@ -434,63 +420,73 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree, assert(prefix_len * 2 >= n); memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len); while (tree_entry(&desc, &entry)) { - path_len = strlen(entry.path); - len = get_oid_hex_segment(entry.path, path_len, - object_oid.hash + prefix_len, GIT_SHA1_RAWSZ - prefix_len); - if (len < 0) - goto handle_non_note; /* entry.path is not a SHA1 */ - len += prefix_len; + unsigned char type; + struct leaf_node *l; + size_t path_len = strlen(entry.path); + + if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) { + /* This is potentially the remainder of the SHA-1 */ + + if (!S_ISREG(entry.mode)) + /* notes must be blobs */ + goto handle_non_note; + + if (hex_to_bytes(object_oid.hash + prefix_len, entry.path, + GIT_SHA1_RAWSZ - prefix_len)) + goto handle_non_note; /* entry.path is not a SHA1 */ - /* - * If object SHA1 is complete (len == 20), assume note object - * If object SHA1 is incomplete (len < 20), and current - * component consists of 2 hex chars, assume note subtree - */ - if (len <= GIT_SHA1_RAWSZ) { type = PTR_TYPE_NOTE; - l = (struct leaf_node *) - xcalloc(1, sizeof(struct leaf_node)); - oidcpy(&l->key_oid, &object_oid); - oidcpy(&l->val_oid, entry.oid); - if (len < GIT_SHA1_RAWSZ) { - if (!S_ISDIR(entry.mode) || path_len != 2) - goto handle_non_note; /* not subtree */ - l->key_oid.hash[KEY_INDEX] = (unsigned char) len; - type = PTR_TYPE_SUBTREE; - } - if (note_tree_insert(t, node, n, l, type, - combine_notes_concatenate)) - die("Failed to load %s %s into notes tree " - "from %s", - type == PTR_TYPE_NOTE ? "note" : "subtree", - oid_to_hex(&l->key_oid), t->ref); + } else if (path_len == 2) { + /* This is potentially an internal node */ + size_t len = prefix_len; + + if (!S_ISDIR(entry.mode)) + /* internal nodes must be trees */ + goto handle_non_note; + + if (hex_to_bytes(object_oid.hash + len++, entry.path, 1)) + goto handle_non_note; /* entry.path is not a SHA1 */ + + /* + * Pad the rest of the SHA-1 with zeros, + * except for the last byte, where we write + * the length: + */ + memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1); + object_oid.hash[KEY_INDEX] = (unsigned char)len; + + type = PTR_TYPE_SUBTREE; + } else { + /* This can't be part of a note */ + goto handle_non_note; } + + l = xcalloc(1, sizeof(*l)); + oidcpy(&l->key_oid, &object_oid); + oidcpy(&l->val_oid, entry.oid); + if (note_tree_insert(t, node, n, l, type, + combine_notes_concatenate)) + die("Failed to load %s %s into notes tree " + "from %s", + type == PTR_TYPE_NOTE ? "note" : "subtree", + oid_to_hex(&l->key_oid), t->ref); + continue; handle_non_note: /* - * Determine full path for this non-note entry: - * The filename is already found in entry.path, but the - * directory part of the path must be deduced from the subtree - * containing this entry. We assume here that the overall notes - * tree follows a strict byte-based progressive fanout - * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not - * e.g. 4/36 fanout). This means that if a non-note is found at - * path "dead/beef", the following code will register it as - * being found on "de/ad/beef". - * On the other hand, if you use such non-obvious non-note - * paths in the middle of a notes tree, you deserve what's - * coming to you ;). Note that for non-notes that are not - * SHA1-like at the top level, there will be no problems. - * - * To conclude, it is strongly advised to make sure non-notes - * have at least one non-hex character in the top-level path - * component. + * Determine full path for this non-note entry. The + * filename is already found in entry.path, but the + * directory part of the path must be deduced from the + * subtree containing this entry based on our + * knowledge that the overall notes tree follows a + * strict byte-based progressive fanout structure + * (i.e. using 2/38, 2/2/36, etc. fanouts). */ { struct strbuf non_note_path = STRBUF_INIT; const char *q = oid_to_hex(&subtree->key_oid); - int i; + size_t i; for (i = 0; i < prefix_len; i++) { strbuf_addch(&non_note_path, *q++); strbuf_addch(&non_note_path, *q++); diff --git a/pathspec.c b/pathspec.c index e2a23ebc96..1079362450 100644 --- a/pathspec.c +++ b/pathspec.c @@ -536,7 +536,7 @@ void parse_pathspec(struct pathspec *pathspec, { struct pathspec_item *item; const char *entry = argv ? *argv : NULL; - int i, n, prefixlen, warn_empty_string, nr_exclude = 0; + int i, n, prefixlen, nr_exclude = 0; memset(pathspec, 0, sizeof(*pathspec)); @@ -569,13 +569,10 @@ void parse_pathspec(struct pathspec *pathspec, } n = 0; - warn_empty_string = 1; while (argv[n]) { - if (*argv[n] == '\0' && warn_empty_string) { - warning(_("empty strings as pathspecs will be made invalid in upcoming releases. " - "please use . instead if you meant to match all paths")); - warn_empty_string = 0; - } + if (*argv[n] == '\0') + die("empty string is not a valid pathspec. " + "please use . instead if you meant to match all paths"); n++; } diff --git a/remote.c b/remote.c index 43c317e4e9..4113090069 100644 --- a/remote.c +++ b/remote.c @@ -2084,7 +2084,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb) _(" (use \"git branch --unset-upstream\" to fixup)\n")); } else if (!ours && !theirs) { strbuf_addf(sb, - _("Your branch is up-to-date with '%s'.\n"), + _("Your branch is up to date with '%s'.\n"), base); } else if (!theirs) { strbuf_addf(sb, diff --git a/sha1-lookup.h b/sha1-lookup.h index 20af285681..cf5314f402 100644 --- a/sha1-lookup.h +++ b/sha1-lookup.h @@ -7,10 +7,4 @@ extern int sha1_pos(const unsigned char *sha1, void *table, size_t nr, sha1_access_fn fn); - -extern int sha1_entry_pos(const void *table, - size_t elem_size, - size_t key_offset, - unsigned lo, unsigned hi, unsigned nr, - const unsigned char *key); #endif diff --git a/sha1_file.c b/sha1_file.c index f56bb5cae7..5f71bbac3e 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -30,7 +30,7 @@ #include "quote.h" #include "packfile.h" -const unsigned char null_sha1[20]; +const unsigned char null_sha1[GIT_MAX_RAWSZ]; const struct object_id null_oid; const struct object_id empty_tree_oid = { EMPTY_TREE_SHA1_BIN_LITERAL diff --git a/sha1dc_git.c b/sha1dc_git.c index 4d32b4f77e..e0cc9d988c 100644 --- a/sha1dc_git.c +++ b/sha1dc_git.c @@ -1,8 +1,19 @@ +#include "cache.h" + +#ifdef DC_SHA1_EXTERNAL /* - * This code is included at the end of sha1dc/sha1.c with the - * SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C macro. + * Same as SHA1DCInit, but with default save_hash=0 */ +void git_SHA1DCInit(SHA1_CTX *ctx) +{ + SHA1DCInit(ctx); + SHA1DCSetSafeHash(ctx, 0); +} +#endif +/* + * Same as SHA1DCFinal, but convert collision attack case into a verbose die(). + */ void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx) { if (!SHA1DCFinal(hash, ctx)) @@ -11,6 +22,9 @@ void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx) sha1_to_hex(hash)); } +/* + * Same as SHA1DCUpdate, but adjust types to match git's usual interface. + */ void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, unsigned long len) { const char *data = vdata; diff --git a/sha1dc_git.h b/sha1dc_git.h index a8a5c1da16..a8c2729278 100644 --- a/sha1dc_git.h +++ b/sha1dc_git.h @@ -1,19 +1,23 @@ -/* - * This code is included at the end of sha1dc/sha1.h with the - * SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H macro. - */ +/* Plumbing with collition-detecting SHA1 code */ -/* - * Same as SHA1DCFinal, but convert collision attack case into a verbose die(). - */ -void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *); +#ifdef DC_SHA1_SUBMODULE +#include "sha1collisiondetection/lib/sha1.h" +#elif defined(DC_SHA1_EXTERNAL) +#include +#else +#include "sha1dc/sha1.h" +#endif + +#ifdef DC_SHA1_EXTERNAL +void git_SHA1DCInit(SHA1_CTX *); +#else +#define git_SHA1DCInit SHA1DCInit +#endif -/* - * Same as SHA1DCUpdate, but adjust types to match git's usual interface. - */ +void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *); void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len); #define platform_SHA_CTX SHA1_CTX -#define platform_SHA1_Init SHA1DCInit +#define platform_SHA1_Init git_SHA1DCInit #define platform_SHA1_Update git_SHA1DCUpdate #define platform_SHA1_Final git_SHA1DCFinal diff --git a/strbuf.h b/strbuf.h index e705b94db5..7496cb8ec5 100644 --- a/strbuf.h +++ b/strbuf.h @@ -147,7 +147,10 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) if (len > (sb->alloc ? sb->alloc - 1 : 0)) die("BUG: strbuf_setlen() beyond buffer"); sb->len = len; - sb->buf[len] = '\0'; + if (sb->buf != strbuf_slopbuf) + sb->buf[len] = '\0'; + else + assert(!strbuf_slopbuf[0]); } /** diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index deb3ae7813..68108d956a 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -315,7 +315,7 @@ test_expect_success 'setup master' ' echo >.gitattributes && git checkout -b master && git add .gitattributes && - git commit -m "add .gitattributes" "" && + git commit -m "add .gitattributes" . && printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\nLINETWO\nLINETHREE" >LF && printf "\$Id: 0000000000000000000000000000000000000000 \$\r\nLINEONE\r\nLINETWO\r\nLINETHREE" >CRLF && printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\r\nLINETWO\nLINETHREE" >CRLF_mix_LF && diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 9d707d2a40..d971649979 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -162,6 +162,19 @@ test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD' grep "^0\{40\}.*$msg$" .git/logs/HEAD ' +test_expect_success 'git branch -M should leave orphaned HEAD alone' ' + git init orphan && + ( + cd orphan && + test_commit initial && + git checkout --orphan lonely && + grep lonely .git/HEAD && + test_path_is_missing .git/refs/head/lonely && + git branch -M master mistress && + grep lonely .git/HEAD + ) +' + test_expect_success 'resulting reflog can be shown by log -g' ' oid=$(git rev-parse HEAD) && cat >expect <<-EOF && @@ -559,6 +572,7 @@ test_expect_success 'use --set-upstream-to modify HEAD' ' test_expect_success 'use --set-upstream-to modify a particular branch' ' git branch my13 && git branch --set-upstream-to master my13 && + test_when_finished "git branch --unset-upstream my13" && test "$(git config branch.my13.remote)" = "." && test "$(git config branch.my13.merge)" = "refs/heads/master" ' @@ -604,38 +618,8 @@ test_expect_success 'test --unset-upstream on a particular branch' ' test_must_fail git config branch.my14.merge ' -test_expect_success '--set-upstream shows message when creating a new branch that exists as remote-tracking' ' - git update-ref refs/remotes/origin/master HEAD && - git branch --set-upstream origin/master 2>actual && - test_when_finished git update-ref -d refs/remotes/origin/master && - test_when_finished git branch -d origin/master && - cat >expected <actual && - test_when_finished git branch --unset-upstream master && - cat >expected <actual && - test_when_finished git branch --unset-upstream my13 && - cat >expected <"$1" diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index f8568f8841..81c6059a2d 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -858,9 +858,8 @@ test_expect_success 'rm files with two different errors' ' test_i18ncmp expect actual ' -test_expect_success 'rm empty string should invoke warning' ' - git rm -rf "" 2>output && - test_i18ngrep "warning: empty strings" output +test_expect_success 'rm empty string should fail' ' + test_must_fail git rm -rf "" ' test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 0aae21d698..2748805642 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -331,9 +331,8 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out test_i18ncmp expect.err actual.err ' -test_expect_success 'git add empty string should invoke warning' ' - git add "" 2>output && - test_i18ngrep "warning: empty strings" output +test_expect_success 'git add empty string should fail' ' + test_must_fail git add "" ' test_expect_success 'git add --chmod=[+-]x stages correctly' ' diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index b04d955bfa..897f6f06d5 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -7,11 +7,15 @@ test_description='git archive attribute tests' SUBSTFORMAT='%H (%h)%n' test_expect_exists() { - test_expect_success " $1 exists" "test -e $1" + test_expect_${2:-success} " $1 exists" "test -e $1" } test_expect_missing() { - test_expect_success " $1 does not exist" "test ! -e $1" + test_expect_${2:-success} " $1 does not exist" "test ! -e $1" +} + +extract_tar_to_dir () { + (mkdir "$1" && cd "$1" && "$TAR" xf -) <"$1.tar" } test_expect_success 'setup' ' @@ -21,12 +25,19 @@ test_expect_success 'setup' ' echo ignored by tree >ignored-by-tree && echo ignored-by-tree export-ignore >.gitattributes && - git add ignored-by-tree .gitattributes && + mkdir ignored-by-tree.d && + >ignored-by-tree.d/file && + echo ignored-by-tree.d export-ignore >>.gitattributes && + git add ignored-by-tree ignored-by-tree.d .gitattributes && echo ignored by worktree >ignored-by-worktree && echo ignored-by-worktree export-ignore >.gitattributes && git add ignored-by-worktree && + mkdir excluded-by-pathspec.d && + >excluded-by-pathspec.d/file && + git add excluded-by-pathspec.d && + printf "A\$Format:%s\$O" "$SUBSTFORMAT" >nosubstfile && printf "A\$Format:%s\$O" "$SUBSTFORMAT" >substfile1 && printf "A not substituted O" >substfile2 && @@ -46,7 +57,37 @@ test_expect_success 'git archive' ' test_expect_missing archive/ignored test_expect_missing archive/ignored-by-tree +test_expect_missing archive/ignored-by-tree.d +test_expect_missing archive/ignored-by-tree.d/file test_expect_exists archive/ignored-by-worktree +test_expect_exists archive/excluded-by-pathspec.d +test_expect_exists archive/excluded-by-pathspec.d/file + +test_expect_success 'git archive with pathspec' ' + git archive HEAD ":!excluded-by-pathspec.d" >archive-pathspec.tar && + extract_tar_to_dir archive-pathspec +' + +test_expect_missing archive-pathspec/ignored +test_expect_missing archive-pathspec/ignored-by-tree +test_expect_missing archive-pathspec/ignored-by-tree.d +test_expect_missing archive-pathspec/ignored-by-tree.d/file +test_expect_exists archive-pathspec/ignored-by-worktree +test_expect_missing archive-pathspec/excluded-by-pathspec.d failure +test_expect_missing archive-pathspec/excluded-by-pathspec.d/file + +test_expect_success 'git archive with wildcard pathspec' ' + git archive HEAD ":!excluded-by-p*" >archive-pathspec-wildcard.tar && + extract_tar_to_dir archive-pathspec-wildcard +' + +test_expect_missing archive-pathspec-wildcard/ignored +test_expect_missing archive-pathspec-wildcard/ignored-by-tree +test_expect_missing archive-pathspec-wildcard/ignored-by-tree.d +test_expect_missing archive-pathspec-wildcard/ignored-by-tree.d/file +test_expect_exists archive-pathspec-wildcard/ignored-by-worktree +test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d +test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d/file test_expect_success 'git archive with worktree attributes' ' git archive --worktree-attributes HEAD >worktree.tar && diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index 97a07655a0..8f17fd9da8 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -100,7 +100,7 @@ test_expect_success 'checkout (up-to-date with upstream)' ' ( cd test && git checkout b6 ) >actual && - test_i18ngrep "Your branch is up-to-date with .origin/master" actual + test_i18ngrep "Your branch is up to date with .origin/master" actual ' test_expect_success 'status (diverged from upstream)' ' @@ -130,7 +130,7 @@ test_expect_success 'status (up-to-date with upstream)' ' # reports nothing to commit test_must_fail git commit --dry-run ) >actual && - test_i18ngrep "Your branch is up-to-date with .origin/master" actual + test_i18ngrep "Your branch is up to date with .origin/master" actual ' cat >expect <<\EOF @@ -188,35 +188,29 @@ test_expect_success 'fail to track annotated tags' ' test_must_fail git checkout heavytrack ' -test_expect_success 'setup tracking with branch --set-upstream on existing branch' ' +test_expect_success '--set-upstream-to does not change branch' ' git branch from-master master && - test_must_fail git config branch.from-master.merge > actual && - git branch --set-upstream from-master master && - git config branch.from-master.merge > actual && - grep -q "^refs/heads/master$" actual -' - -test_expect_success '--set-upstream does not change branch' ' + git branch --set-upstream-to master from-master && git branch from-master2 master && test_must_fail git config branch.from-master2.merge > actual && git rev-list from-master2 && git update-ref refs/heads/from-master2 from-master2^ && git rev-parse from-master2 >expect2 && - git branch --set-upstream from-master2 master && + git branch --set-upstream-to master from-master2 && git config branch.from-master.merge > actual && git rev-parse from-master2 >actual2 && grep -q "^refs/heads/master$" actual && cmp expect2 actual2 ' -test_expect_success '--set-upstream @{-1}' ' - git checkout from-master && +test_expect_success '--set-upstream-to @{-1}' ' + git checkout follower && git checkout from-master2 && git config branch.from-master2.merge > expect2 && - git branch --set-upstream @{-1} follower && + git branch --set-upstream-to @{-1} from-master && git config branch.from-master.merge > actual && git config branch.from-master2.merge > actual2 && - git branch --set-upstream from-master follower && + git branch --set-upstream-to follower from-master && git config branch.from-master.merge > expect && test_cmp expect2 actual2 && test_cmp expect actual diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index d1e4e8ad19..f30980895c 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -148,6 +148,8 @@ cat >expected-cc <<\EOF !two@example.com! !three@example.com! !four@example.com! +!five@example.com! +!six@example.com! EOF " @@ -161,6 +163,8 @@ test_expect_success $PREREQ 'cc trailer with various syntax' ' Cc: # trailing comments are ignored Cc: , one address per line Cc: "Some # Body" [ ] + Cc: five@example.com # not.six@example.com + Cc: six@example.com, not.seven@example.com EOF clean_fake_sendmail && git send-email -1 --to=recipient@example.com \ diff --git a/templates/hooks--pre-rebase.sample b/templates/hooks--pre-rebase.sample index b7f81c198e..db5feab8a1 100755 --- a/templates/hooks--pre-rebase.sample +++ b/templates/hooks--pre-rebase.sample @@ -58,7 +58,7 @@ then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then - echo >&2 "$topic is already up-to-date with master" + echo >&2 "$topic is already up to date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 diff --git a/transport-helper.c b/transport-helper.c index 8f68d69a86..f50b34df2d 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1117,6 +1117,13 @@ int transport_helper_init(struct transport *transport, const char *name) __attribute__((format (printf, 1, 2))) static void transfer_debug(const char *fmt, ...) { + /* + * NEEDSWORK: This function is sometimes used from multiple threads, and + * we end up using debug_enabled racily. That "should not matter" since + * we always write the same value, but it's still wrong. This function + * is listed in .tsan-suppressions for the time being. + */ + va_list args; char msgbuf[PBUFFERSIZE]; static int debug_enabled = -1; diff --git a/unpack-trees.c b/unpack-trees.c index 68d34259c6..71b70ccb12 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -163,7 +163,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, msgs[ERROR_BIND_OVERLAP] = _("Entry '%s' overlaps with '%s'. Cannot bind."); msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] = - _("Cannot update sparse checkout: the following entries are not up-to-date:\n%s"); + _("Cannot update sparse checkout: the following entries are not up to date:\n%s"); msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] = _("The following working tree files would be overwritten by sparse checkout update:\n%s"); msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] = @@ -383,8 +383,8 @@ static int check_updates(struct unpack_trees_options *o) } } } - errs |= finish_delayed_checkout(&state); stop_progress(&progress); + errs |= finish_delayed_checkout(&state); if (o->update) git_attr_set_direction(GIT_ATTR_CHECKIN, NULL); return errs != 0; diff --git a/worktree.c b/worktree.c index e28ffbeb09..c0c5a2b373 100644 --- a/worktree.c +++ b/worktree.c @@ -30,7 +30,7 @@ static void add_head_info(struct worktree *wt) target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt), "HEAD", - RESOLVE_REF_READING, + 0, wt->head_sha1, &flags); if (!target) return;