summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/coccinelle/commit.cocci6
-rw-r--r--contrib/coccinelle/object_id.cocci50
-rw-r--r--contrib/completion/git-completion.bash443
-rw-r--r--contrib/credential/netrc/Makefile3
-rwxr-xr-xcontrib/credential/netrc/t-git-credential-netrc.sh9
-rwxr-xr-xcontrib/credential/netrc/test.pl5
-rw-r--r--contrib/git-jump/README12
-rwxr-xr-xcontrib/git-jump/git-jump2
-rwxr-xr-xcontrib/mw-to-git/t/t9360-mw-to-git-clone.sh2
-rwxr-xr-xcontrib/subtree/git-subtree.sh129
-rwxr-xr-xcontrib/subtree/t/t7900-subtree.sh121
-rw-r--r--contrib/vscode/.gitattributes1
-rw-r--r--contrib/vscode/README.md14
-rwxr-xr-xcontrib/vscode/init.sh375
14 files changed, 655 insertions, 517 deletions
diff --git a/contrib/coccinelle/commit.cocci b/contrib/coccinelle/commit.cocci
index a7e9215ffc..c49aa558f0 100644
--- a/contrib/coccinelle/commit.cocci
+++ b/contrib/coccinelle/commit.cocci
@@ -12,13 +12,13 @@ expression c;
// These excluded functions must access c->maybe_tree direcly.
@@
-identifier f !~ "^(get_commit_tree|get_commit_tree_in_graph|load_tree_for_commit)$";
+identifier f !~ "^(get_commit_tree|get_commit_tree_in_graph_one|load_tree_for_commit)$";
expression c;
@@
- f(...) {...
+ f(...) {<...
- c->maybe_tree
+ get_commit_tree(c)
- ...}
+ ...>}
@@
expression c;
diff --git a/contrib/coccinelle/object_id.cocci b/contrib/coccinelle/object_id.cocci
index 09afdbf994..d8bdb48712 100644
--- a/contrib/coccinelle/object_id.cocci
+++ b/contrib/coccinelle/object_id.cocci
@@ -20,10 +20,10 @@ expression E1;
identifier f != oid_to_hex;
expression E1;
@@
- f(...) {...
+ f(...) {<...
- sha1_to_hex(E1->hash)
+ oid_to_hex(E1)
- ...}
+ ...>}
@@
expression E1, E2;
@@ -35,10 +35,10 @@ expression E1, E2;
identifier f != oid_to_hex_r;
expression E1, E2;
@@
- f(...) {...
+ f(...) {<...
- sha1_to_hex_r(E1, E2->hash)
+ oid_to_hex_r(E1, E2)
- ...}
+ ...>}
@@
expression E1;
@@ -50,10 +50,10 @@ expression E1;
identifier f != oidclr;
expression E1;
@@
- f(...) {...
+ f(...) {<...
- hashclr(E1->hash)
+ oidclr(E1)
- ...}
+ ...>}
@@
expression E1, E2;
@@ -65,10 +65,10 @@ expression E1, E2;
identifier f != oidcmp;
expression E1, E2;
@@
- f(...) {...
+ f(...) {<...
- hashcmp(E1->hash, E2->hash)
+ oidcmp(E1, E2)
- ...}
+ ...>}
@@
expression E1, E2;
@@ -92,10 +92,10 @@ expression E1, E2;
identifier f != oidcpy;
expression E1, E2;
@@
- f(...) {...
+ f(...) {<...
- hashcpy(E1->hash, E2->hash)
+ oidcpy(E1, E2)
- ...}
+ ...>}
@@
expression E1, E2;
@@ -108,3 +108,33 @@ expression E1, E2;
@@
- hashcpy(E1.hash, E2->hash)
+ oidcpy(&E1, E2)
+
+@@
+expression E1, E2;
+@@
+- oidcmp(E1, E2) == 0
++ oideq(E1, E2)
+
+@@
+identifier f != hasheq;
+expression E1, E2;
+@@
+ f(...) {<...
+- hashcmp(E1, E2) == 0
++ hasheq(E1, E2)
+ ...>}
+
+@@
+expression E1, E2;
+@@
+- oidcmp(E1, E2) != 0
++ !oideq(E1, E2)
+
+@@
+identifier f != hasheq;
+expression E1, E2;
+@@
+ f(...) {<...
+- hashcmp(E1, E2) != 0
++ !hasheq(E1, E2)
+ ...>}
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index dd3e925843..db7fd87b6b 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -330,9 +330,32 @@ __gitcomp ()
case "$cur_" in
--*=)
;;
+ --no-*)
+ local c i=0 IFS=$' \t\n'
+ for c in $1; do
+ if [[ $c == "--" ]]; then
+ continue
+ fi
+ c="$c${4-}"
+ if [[ $c == "$cur_"* ]]; then
+ case $c in
+ --*=*|*.) ;;
+ *) c="$c " ;;
+ esac
+ COMPREPLY[i++]="${2-}$c"
+ fi
+ done
+ ;;
*)
local c i=0 IFS=$' \t\n'
for c in $1; do
+ if [[ $c == "--" ]]; then
+ c="--no-...${4-}"
+ if [[ $c == "$cur_"* ]]; then
+ COMPREPLY[i++]="${2-}$c "
+ fi
+ break
+ fi
c="$c${4-}"
if [[ $c == "$cur_"* ]]; then
case $c in
@@ -920,6 +943,7 @@ __git_complete_remote_or_refspec ()
*) ;;
esac
;;
+ --multiple) no_complete_refspec=1; break ;;
-*) ;;
*) remote="$i"; break ;;
esac
@@ -1161,7 +1185,7 @@ _git_am ()
return
;;
--*)
- __gitcomp_builtin am "--no-utf8" \
+ __gitcomp_builtin am "" \
"$__git_am_inprogress_options"
return
esac
@@ -1261,9 +1285,7 @@ _git_branch ()
__git_complete_refs --cur="${cur##--set-upstream-to=}"
;;
--*)
- __gitcomp_builtin branch "--no-color --no-abbrev
- --no-track --no-column
- "
+ __gitcomp_builtin branch
;;
*)
if [ $only_local_ref = "y" -a $has_r = "n" ]; then
@@ -1304,7 +1326,7 @@ _git_checkout ()
__gitcomp "diff3 merge" "" "${cur##--conflict=}"
;;
--*)
- __gitcomp_builtin checkout "--no-track --no-recurse-submodules"
+ __gitcomp_builtin checkout
;;
*)
# check if --track, --no-track, or --no-guess was specified
@@ -1367,7 +1389,7 @@ _git_clone ()
{
case "$cur" in
--*)
- __gitcomp_builtin clone "--no-single-branch"
+ __gitcomp_builtin clone
return
;;
esac
@@ -1400,7 +1422,7 @@ _git_commit ()
return
;;
--*)
- __gitcomp_builtin commit "--no-edit --verify"
+ __gitcomp_builtin commit
return
esac
@@ -1503,7 +1525,7 @@ _git_fetch ()
return
;;
--*)
- __gitcomp_builtin fetch "--no-tags"
+ __gitcomp_builtin fetch
return
;;
esac
@@ -1540,7 +1562,7 @@ _git_fsck ()
{
case "$cur" in
--*)
- __gitcomp_builtin fsck "--no-reflogs"
+ __gitcomp_builtin fsck
return
;;
esac
@@ -1646,7 +1668,7 @@ _git_ls_files ()
{
case "$cur" in
--*)
- __gitcomp_builtin ls-files "--no-empty-directory"
+ __gitcomp_builtin ls-files
return
;;
esac
@@ -1797,12 +1819,7 @@ _git_merge ()
case "$cur" in
--*)
- __gitcomp_builtin merge "--no-rerere-autoupdate
- --no-commit --no-edit --no-ff
- --no-log --no-progress
- --no-squash --no-stat
- --no-verify-signatures
- "
+ __gitcomp_builtin merge
return
esac
__git_complete_refs
@@ -1901,10 +1918,7 @@ _git_pull ()
return
;;
--*)
- __gitcomp_builtin pull "--no-autostash --no-commit --no-edit
- --no-ff --no-log --no-progress --no-rebase
- --no-squash --no-stat --no-tags
- --no-verify-signatures"
+ __gitcomp_builtin pull
return
;;
@@ -1963,6 +1977,20 @@ _git_push ()
__git_complete_remote_or_refspec
}
+_git_range_diff ()
+{
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --creation-factor= --no-dual-color
+ $__git_diff_common_options
+ "
+ return
+ ;;
+ esac
+ __git_complete_revlist
+}
+
_git_rebase ()
{
__git_find_repo_path
@@ -2095,7 +2123,7 @@ _git_status ()
return
;;
--*)
- __gitcomp_builtin status "--no-column"
+ __gitcomp_builtin status
return
;;
esac
@@ -2142,9 +2170,24 @@ __git_config_get_set_variables ()
__git config $config_file --name-only --list
}
+__git_config_vars=
+__git_compute_config_vars ()
+{
+ test -n "$__git_config_vars" ||
+ __git_config_vars="$(git help --config-for-completion | sort | uniq)"
+}
+
_git_config ()
{
- case "$prev" in
+ local varname
+
+ if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then
+ varname="${prev,,}"
+ else
+ varname="$(echo "$prev" |tr A-Z a-z)"
+ fi
+
+ case "$varname" in
branch.*.remote|branch.*.pushremote)
__gitcomp_nl "$(__git_remotes)"
return
@@ -2242,20 +2285,20 @@ _git_config ()
;;
branch.*.*)
local pfx="${cur%.*}." cur_="${cur##*.}"
- __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_"
+ __gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_"
return
;;
branch.*)
local pfx="${cur%.*}." cur_="${cur#*.}"
__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
- __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
+ __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_"
return
;;
guitool.*.*)
local pfx="${cur%.*}." cur_="${cur##*.}"
__gitcomp "
- argprompt cmd confirm needsfile noconsole norescan
- prompt revprompt revunmerged title
+ argPrompt cmd confirm needsFile noConsole noRescan
+ prompt revPrompt revUnmerged title
" "$pfx" "$cur_"
return
;;
@@ -2284,14 +2327,14 @@ _git_config ()
local pfx="${cur%.*}." cur_="${cur##*.}"
__gitcomp "
url proxy fetch push mirror skipDefaultUpdate
- receivepack uploadpack tagopt pushurl
+ receivepack uploadpack tagOpt pushurl
" "$pfx" "$cur_"
return
;;
remote.*)
local pfx="${cur%.*}." cur_="${cur#*.}"
__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
- __gitcomp_nl_append "pushdefault" "$pfx" "$cur_"
+ __gitcomp_nl_append "pushDefault" "$pfx" "$cur_"
return
;;
url.*.*)
@@ -2299,333 +2342,14 @@ _git_config ()
__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"
return
;;
+ *.*)
+ __git_compute_config_vars
+ __gitcomp "$__git_config_vars"
+ ;;
+ *)
+ __git_compute_config_vars
+ __gitcomp "$(echo "$__git_config_vars" | sed 's/\.[^ ]*/./g')"
esac
- __gitcomp "
- add.ignoreErrors
- advice.amWorkDir
- advice.commitBeforeMerge
- advice.detachedHead
- advice.implicitIdentity
- advice.pushAlreadyExists
- advice.pushFetchFirst
- advice.pushNeedsForce
- advice.pushNonFFCurrent
- advice.pushNonFFMatching
- advice.pushUpdateRejected
- advice.resolveConflict
- advice.rmHints
- advice.statusHints
- advice.statusUoption
- advice.ignoredHook
- alias.
- am.keepcr
- am.threeWay
- apply.ignorewhitespace
- apply.whitespace
- branch.autosetupmerge
- branch.autosetuprebase
- browser.
- clean.requireForce
- color.branch
- color.branch.current
- color.branch.local
- color.branch.plain
- color.branch.remote
- color.decorate.HEAD
- color.decorate.branch
- color.decorate.remoteBranch
- color.decorate.stash
- color.decorate.tag
- color.diff
- color.diff.commit
- color.diff.frag
- color.diff.func
- color.diff.meta
- color.diff.new
- color.diff.old
- color.diff.plain
- color.diff.whitespace
- color.grep
- color.grep.context
- color.grep.filename
- color.grep.function
- color.grep.linenumber
- color.grep.match
- color.grep.selected
- color.grep.separator
- color.interactive
- color.interactive.error
- color.interactive.header
- color.interactive.help
- color.interactive.prompt
- color.pager
- color.showbranch
- color.status
- color.status.added
- color.status.changed
- color.status.header
- color.status.localBranch
- color.status.nobranch
- color.status.remoteBranch
- color.status.unmerged
- color.status.untracked
- color.status.updated
- color.ui
- commit.cleanup
- commit.gpgSign
- commit.status
- commit.template
- commit.verbose
- core.abbrev
- core.askpass
- core.attributesfile
- core.autocrlf
- core.bare
- core.bigFileThreshold
- core.checkStat
- core.commentChar
- core.commitGraph
- core.compression
- core.createObject
- core.deltaBaseCacheLimit
- core.editor
- core.eol
- core.excludesfile
- core.fileMode
- core.fsyncobjectfiles
- core.gitProxy
- core.hideDotFiles
- core.hooksPath
- core.ignoreStat
- core.ignorecase
- core.logAllRefUpdates
- core.loosecompression
- core.notesRef
- core.packedGitLimit
- core.packedGitWindowSize
- core.packedRefsTimeout
- core.pager
- core.precomposeUnicode
- core.preferSymlinkRefs
- core.preloadindex
- core.protectHFS
- core.protectNTFS
- core.quotepath
- core.repositoryFormatVersion
- core.safecrlf
- core.sharedRepository
- core.sparseCheckout
- core.splitIndex
- core.sshCommand
- core.symlinks
- core.trustctime
- core.untrackedCache
- core.warnAmbiguousRefs
- core.whitespace
- core.worktree
- credential.helper
- credential.useHttpPath
- credential.username
- credentialCache.ignoreSIGHUP
- diff.autorefreshindex
- diff.external
- diff.ignoreSubmodules
- diff.mnemonicprefix
- diff.noprefix
- diff.renameLimit
- diff.renames
- diff.statGraphWidth
- diff.submodule
- diff.suppressBlankEmpty
- diff.tool
- diff.wordRegex
- diff.algorithm
- difftool.
- difftool.prompt
- fetch.recurseSubmodules
- fetch.unpackLimit
- format.attach
- format.cc
- format.coverLetter
- format.from
- format.headers
- format.numbered
- format.pretty
- format.signature
- format.signoff
- format.subjectprefix
- format.suffix
- format.thread
- format.to
- gc.
- gc.aggressiveDepth
- gc.aggressiveWindow
- gc.auto
- gc.autoDetach
- gc.autopacklimit
- gc.logExpiry
- gc.packrefs
- gc.pruneexpire
- gc.reflogexpire
- gc.reflogexpireunreachable
- gc.rerereresolved
- gc.rerereunresolved
- gc.worktreePruneExpire
- gitcvs.allbinary
- gitcvs.commitmsgannotation
- gitcvs.dbTableNamePrefix
- gitcvs.dbdriver
- gitcvs.dbname
- gitcvs.dbpass
- gitcvs.dbuser
- gitcvs.enabled
- gitcvs.logfile
- gitcvs.usecrlfattr
- guitool.
- gui.blamehistoryctx
- gui.commitmsgwidth
- gui.copyblamethreshold
- gui.diffcontext
- gui.encoding
- gui.fastcopyblame
- gui.matchtrackingbranch
- gui.newbranchtemplate
- gui.pruneduringfetch
- gui.spellingdictionary
- gui.trustmtime
- help.autocorrect
- help.browser
- help.format
- http.lowSpeedLimit
- http.lowSpeedTime
- http.maxRequests
- http.minSessions
- http.noEPSV
- http.postBuffer
- http.proxy
- http.sslCipherList
- http.sslVersion
- http.sslCAInfo
- http.sslCAPath
- http.sslCert
- http.sslCertPasswordProtected
- http.sslKey
- http.sslVerify
- http.useragent
- i18n.commitEncoding
- i18n.logOutputEncoding
- imap.authMethod
- imap.folder
- imap.host
- imap.pass
- imap.port
- imap.preformattedHTML
- imap.sslverify
- imap.tunnel
- imap.user
- init.templatedir
- instaweb.browser
- instaweb.httpd
- instaweb.local
- instaweb.modulepath
- instaweb.port
- interactive.singlekey
- log.date
- log.decorate
- log.showroot
- mailmap.file
- man.
- man.viewer
- merge.
- merge.conflictstyle
- merge.log
- merge.renameLimit
- merge.renormalize
- merge.stat
- merge.tool
- merge.verbosity
- mergetool.
- mergetool.keepBackup
- mergetool.keepTemporaries
- mergetool.prompt
- notes.displayRef
- notes.rewrite.
- notes.rewrite.amend
- notes.rewrite.rebase
- notes.rewriteMode
- notes.rewriteRef
- pack.compression
- pack.deltaCacheLimit
- pack.deltaCacheSize
- pack.depth
- pack.indexVersion
- pack.packSizeLimit
- pack.threads
- pack.window
- pack.windowMemory
- pager.
- pretty.
- pull.octopus
- pull.twohead
- push.default
- push.followTags
- rebase.autosquash
- rebase.stat
- receive.autogc
- receive.denyCurrentBranch
- receive.denyDeleteCurrent
- receive.denyDeletes
- receive.denyNonFastForwards
- receive.fsckObjects
- receive.unpackLimit
- receive.updateserverinfo
- remote.pushdefault
- remotes.
- repack.usedeltabaseoffset
- rerere.autoupdate
- rerere.enabled
- sendemail.
- sendemail.aliasesfile
- sendemail.aliasfiletype
- sendemail.bcc
- sendemail.cc
- sendemail.cccmd
- sendemail.chainreplyto
- sendemail.confirm
- sendemail.envelopesender
- sendemail.from
- sendemail.identity
- sendemail.multiedit
- sendemail.signedoffbycc
- sendemail.smtpdomain
- sendemail.smtpencryption
- sendemail.smtppass
- sendemail.smtpserver
- sendemail.smtpserveroption
- sendemail.smtpserverport
- sendemail.smtpuser
- sendemail.suppresscc
- sendemail.suppressfrom
- sendemail.thread
- sendemail.to
- sendemail.tocmd
- sendemail.validate
- sendemail.smtpbatchsize
- sendemail.smtprelogindelay
- showbranch.default
- status.relativePaths
- status.showUntrackedFiles
- status.submodulesummary
- submodule.
- tar.umask
- transfer.unpackLimit
- url.
- user.email
- user.name
- user.signingkey
- web.browser
- branch. remote.
- "
}
_git_remote ()
@@ -2649,7 +2373,7 @@ _git_remote ()
case "$subcommand,$cur" in
add,--*)
- __gitcomp_builtin remote_add "--no-tags"
+ __gitcomp_builtin remote_add
;;
add,*)
;;
@@ -2666,7 +2390,7 @@ _git_remote ()
__gitcomp_builtin remote_update
;;
update,*)
- __gitcomp "$(__git_get_config_variables "remotes")"
+ __gitcomp "$(__git_remotes) $(__git_get_config_variables "remotes")"
;;
set-url,--*)
__gitcomp_builtin remote_set-url
@@ -2729,7 +2453,7 @@ _git_revert ()
fi
case "$cur" in
--*)
- __gitcomp_builtin revert "--no-edit" \
+ __gitcomp_builtin revert "" \
"$__git_revert_inprogress_options"
return
;;
@@ -2799,7 +2523,7 @@ _git_show_branch ()
{
case "$cur" in
--*)
- __gitcomp_builtin show-branch "--no-color"
+ __gitcomp_builtin show-branch
return
;;
esac
@@ -2844,6 +2568,9 @@ _git_stash ()
drop,--*)
__gitcomp "--quiet"
;;
+ list,--*)
+ __gitcomp "--name-status --oneline --patch-with-stat"
+ ;;
show,--*|branch,--*)
;;
branch,*)
diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile
index 0ffa407191..6174e3bb83 100644
--- a/contrib/credential/netrc/Makefile
+++ b/contrib/credential/netrc/Makefile
@@ -1,3 +1,6 @@
+# The default target of this Makefile is...
+all::
+
test:
./t-git-credential-netrc.sh
diff --git a/contrib/credential/netrc/t-git-credential-netrc.sh b/contrib/credential/netrc/t-git-credential-netrc.sh
index 58191a62f8..07227d0228 100755
--- a/contrib/credential/netrc/t-git-credential-netrc.sh
+++ b/contrib/credential/netrc/t-git-credential-netrc.sh
@@ -17,15 +17,16 @@
# set up test repository
test_expect_success \
- 'set up test repository' \
- 'git config --add gpg.program test.git-config-gpg'
+ 'set up test repository' \
+ 'git config --add gpg.program test.git-config-gpg'
# The external test will outputs its own plan
test_external_has_tap=1
+ export PERL5LIB="$GITPERLLIB"
test_external \
- 'git-credential-netrc' \
- perl "$TEST_DIRECTORY"/../contrib/credential/netrc/test.pl
+ 'git-credential-netrc' \
+ perl "$GIT_BUILD_DIR"/contrib/credential/netrc/test.pl
test_done
)
diff --git a/contrib/credential/netrc/test.pl b/contrib/credential/netrc/test.pl
index 1e1001030e..c0fb3718b2 100755
--- a/contrib/credential/netrc/test.pl
+++ b/contrib/credential/netrc/test.pl
@@ -1,5 +1,4 @@
#!/usr/bin/perl
-use lib (split(/:/, $ENV{GITPERLLIB}));
use warnings;
use strict;
@@ -12,7 +11,6 @@ BEGIN {
# t-git-credential-netrc.sh kicks off our testing, so we have to go
# from there.
Test::More->builder->current_test(1);
- Test::More->builder->no_ending(1);
}
my @global_credential_args = @ARGV;
@@ -104,6 +102,9 @@ $cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get'
ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
+my $is_passing = eval { Test::More->is_passing };
+exit($is_passing ? 0 : 1) unless $@ =~ /Can't locate object method/;
+
sub run_credential
{
my $args = shift @_;
diff --git a/contrib/git-jump/README b/contrib/git-jump/README
index 4484bda410..2f618a7f97 100644
--- a/contrib/git-jump/README
+++ b/contrib/git-jump/README
@@ -25,6 +25,13 @@ git-jump will feed this to the editor:
foo.c:2: printf("hello word!\n");
-----------------------------------
+Or, when running 'git jump grep', column numbers will also be emitted,
+e.g. `git jump grep "hello"` would return:
+
+-----------------------------------
+foo.c:2:9: printf("hello word!\n");
+-----------------------------------
+
Obviously this trivial case isn't that interesting; you could just open
`foo.c` yourself. But when you have many changes scattered across a
project, you can use the editor's support to "jump" from point to point.
@@ -35,7 +42,8 @@ Git-jump can generate four types of interesting lists:
2. The beginning of any merge conflict markers.
- 3. Any grep matches.
+ 3. Any grep matches, including the column of the first match on a
+ line.
4. Any whitespace errors detected by `git diff --check`.
@@ -82,7 +90,7 @@ which does something similar to `git jump grep`. However, it is limited
to positioning the cursor to the correct line in only the first file,
leaving you to locate subsequent hits in that file or other files using
the editor or pager. By contrast, git-jump provides the editor with a
-complete list of files and line numbers for each match.
+complete list of files, lines, and a column number for each match.
Limitations
diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump
index 80ab0590bc..931b0fe3a9 100755
--- a/contrib/git-jump/git-jump
+++ b/contrib/git-jump/git-jump
@@ -52,7 +52,7 @@ mode_merge() {
# editor shows them to us in the status bar.
mode_grep() {
cmd=$(git config jump.grepCmd)
- test -n "$cmd" || cmd="git grep -n"
+ test -n "$cmd" || cmd="git grep -n --column"
$cmd "$@" |
perl -pe '
s/[ \t]+/ /g;
diff --git a/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh b/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
index 22f069db48..cfbfe7ddf6 100755
--- a/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
+++ b/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
@@ -247,7 +247,7 @@ test_expect_success 'Test of resistance to modification of category on wiki for
wiki_editpage Notconsidered "this page will not appear on local" false &&
wiki_editpage Othercategory "this page will not appear on local" false -c=Cattwo &&
wiki_editpage Tobeedited "this page have been modified" true -c=Catone &&
- wiki_delete_page Tobedeleted
+ wiki_delete_page Tobedeleted &&
git clone -c remote.origin.categories="Catone" \
mediawiki::'"$WIKI_URL"' mw_dir_14 &&
wiki_getallpage ref_page_14 Catone &&
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index d3f39a862a..147201dc6c 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -231,12 +231,14 @@ cache_miss () {
}
check_parents () {
- missed=$(cache_miss "$@")
+ missed=$(cache_miss "$1")
+ local indent=$(($2 + 1))
for miss in $missed
do
if ! test -r "$cachedir/notree/$miss"
then
debug " incorrect order: $miss"
+ process_split_commit "$miss" "" "$indent"
fi
done
}
@@ -340,7 +342,12 @@ find_existing_splits () {
revs="$2"
main=
sub=
- git log --grep="^git-subtree-dir: $dir/*\$" \
+ local grep_format="^git-subtree-dir: $dir/*\$"
+ if test -n "$ignore_joins"
+ then
+ grep_format="^Add '$dir/' from commit '"
+ fi
+ git log --grep="$grep_format" \
--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |
while read a b junk
do
@@ -534,6 +541,7 @@ copy_or_skip () {
nonidentical=
p=
gotparents=
+ copycommit=
for parent in $newparents
do
ptree=$(toptree_for_commit $parent) || exit $?
@@ -541,7 +549,24 @@ copy_or_skip () {
if test "$ptree" = "$tree"
then
# an identical parent could be used in place of this rev.
- identical="$parent"
+ if test -n "$identical"
+ then
+ # if a previous identical parent was found, check whether
+ # one is already an ancestor of the other
+ mergebase=$(git merge-base $identical $parent)
+ if test "$identical" = "$mergebase"
+ then
+ # current identical commit is an ancestor of parent
+ identical="$parent"
+ elif test "$parent" != "$mergebase"
+ then
+ # no common history; commit must be copied
+ copycommit=1
+ fi
+ else
+ # first identical parent detected
+ identical="$parent"
+ fi
else
nonidentical="$parent"
fi
@@ -564,7 +589,6 @@ copy_or_skip () {
fi
done
- copycommit=
if test -n "$identical" && test -n "$nonidentical"
then
extras=$(git rev-list --count $identical..$nonidentical)
@@ -598,6 +622,58 @@ ensure_valid_ref_format () {
die "'$1' does not look like a ref"
}
+process_split_commit () {
+ local rev="$1"
+ local parents="$2"
+ local indent=$3
+
+ if test $indent -eq 0
+ then
+ revcount=$(($revcount + 1))
+ else
+ # processing commit without normal parent information;
+ # fetch from repo
+ parents=$(git rev-parse "$rev^@")
+ extracount=$(($extracount + 1))
+ fi
+
+ progress "$revcount/$revmax ($createcount) [$extracount]"
+
+ debug "Processing commit: $rev"
+ exists=$(cache_get "$rev")
+ if test -n "$exists"
+ then
+ debug " prior: $exists"
+ return
+ fi
+ createcount=$(($createcount + 1))
+ debug " parents: $parents"
+ check_parents "$parents" "$indent"
+ newparents=$(cache_get $parents)
+ debug " newparents: $newparents"
+
+ tree=$(subtree_for_commit "$rev" "$dir")
+ debug " tree is: $tree"
+
+ # ugly. is there no better way to tell if this is a subtree
+ # vs. a mainline commit? Does it matter?
+ if test -z "$tree"
+ then
+ set_notree "$rev"
+ if test -n "$newparents"
+ then
+ cache_set "$rev" "$rev"
+ fi
+ return
+ fi
+
+ newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $?
+ debug " newrev is: $newrev"
+ cache_set "$rev" "$newrev"
+ cache_set latest_new "$newrev"
+ cache_set latest_old "$rev"
+}
+
cmd_add () {
if test -e "$dir"
then
@@ -689,12 +765,7 @@ cmd_split () {
done
fi
- if test -n "$ignore_joins"
- then
- unrevs=
- else
- unrevs="$(find_existing_splits "$dir" "$revs")"
- fi
+ unrevs="$(find_existing_splits "$dir" "$revs")"
# We can't restrict rev-list to only $dir here, because some of our
# parents have the $dir contents the root, and those won't match.
@@ -703,45 +774,11 @@ cmd_split () {
revmax=$(eval "$grl" | wc -l)
revcount=0
createcount=0
+ extracount=0
eval "$grl" |
while read rev parents
do
- revcount=$(($revcount + 1))
- progress "$revcount/$revmax ($createcount)"
- debug "Processing commit: $rev"
- exists=$(cache_get "$rev")
- if test -n "$exists"
- then
- debug " prior: $exists"
- continue
- fi
- createcount=$(($createcount + 1))
- debug " parents: $parents"
- newparents=$(cache_get $parents)
- debug " newparents: $newparents"
-
- tree=$(subtree_for_commit "$rev" "$dir")
- debug " tree is: $tree"
-
- check_parents $parents
-
- # ugly. is there no better way to tell if this is a subtree
- # vs. a mainline commit? Does it matter?
- if test -z "$tree"
- then
- set_notree "$rev"
- if test -n "$newparents"
- then
- cache_set "$rev" "$rev"
- fi
- continue
- fi
-
- newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $?
- debug " newrev is: $newrev"
- cache_set "$rev" "$newrev"
- cache_set latest_new "$newrev"
- cache_set latest_old "$rev"
+ process_split_commit "$rev" "$parents" 0
done || exit $?
latest_new=$(cache_get latest_new)
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index d05c613c97..57ff4b25c1 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -540,26 +540,10 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub
git fetch .. subproj-br &&
git merge FETCH_HEAD &&
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chkms
-TXT
-) &&
-
- subfiles=$(git ls-files) &&
- check_equal "$subfiles" "$chkms
-$chks"
+ test_write_lines main-sub1 main-sub2 main-sub3 main-sub4 \
+ sub1 sub2 sub3 sub4 >expect &&
+ git ls-files >actual &&
+ test_cmp expect actual
)
'
@@ -606,25 +590,11 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t
git fetch .. subproj-br &&
git merge FETCH_HEAD &&
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chkms
-TXT
-) &&
- allchanges=$(git log --name-only --pretty=format:"" | sort | sed "/^$/d") &&
- check_equal "$allchanges" "$chkms
-$chks"
+ test_write_lines main-sub1 main-sub2 main-sub3 main-sub4 \
+ sub1 sub2 sub3 sub4 >expect &&
+ git log --name-only --pretty=format:"" >log &&
+ sort <log | sed "/^\$/ d" >actual &&
+ test_cmp expect actual
)
'
@@ -675,29 +645,16 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai
cd "$subtree_test_count" &&
git subtree pull --prefix="sub dir" ./"sub proj" master &&
- chkm="main1
-main2" &&
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chkms
-TXT
-) &&
- mainfiles=$(git ls-files) &&
- check_equal "$mainfiles" "$chkm
-$chkms_sub
-$chks_sub"
-)
+ test_write_lines main1 main2 >chkm &&
+ test_write_lines main-sub1 main-sub2 main-sub3 main-sub4 >chkms &&
+ sed "s,^,sub dir/," chkms >chkms_sub &&
+ test_write_lines sub1 sub2 sub3 sub4 >chks &&
+ sed "s,^,sub dir/," chks >chks_sub &&
+
+ cat chkm chkms_sub chks_sub >expect &&
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
'
next_test
@@ -708,7 +665,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire
test_create_commit "$subtree_test_count/sub proj" sub1 &&
(
cd "$subtree_test_count" &&
- git config log.date relative
+ git config log.date relative &&
git fetch ./"sub proj" master &&
git subtree add --prefix="sub dir" FETCH_HEAD
) &&
@@ -748,37 +705,21 @@ test_expect_success 'make sure each filename changed exactly once in the entire
cd "$subtree_test_count" &&
git subtree pull --prefix="sub dir" ./"sub proj" master &&
- chkm="main1
-main2" &&
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
-$chkms
-TXT
-) &&
+ test_write_lines main1 main2 >chkm &&
+ test_write_lines sub1 sub2 sub3 sub4 >chks &&
+ test_write_lines main-sub1 main-sub2 main-sub3 main-sub4 >chkms &&
+ sed "s,^,sub dir/," chkms >chkms_sub &&
# main-sub?? and /"sub dir"/main-sub?? both change, because those are the
# changes that were split into their own history. And "sub dir"/sub?? never
# change, since they were *only* changed in the subtree branch.
- allchanges=$(git log --name-only --pretty=format:"" | sort | sed "/^$/d") &&
- expected=''"$(cat <<TXT | sort
-$chkms
-$chkm
-$chks
-$chkms_sub
-TXT
-)"'' &&
- check_equal "$allchanges" "$expected"
+ git log --name-only --pretty=format:"" >log &&
+ sort <log >sorted-log &&
+ sed "/^$/ d" sorted-log >actual &&
+
+ cat chkms chkm chks chkms_sub >expect-unsorted &&
+ sort expect-unsorted >expect &&
+ test_cmp expect actual
)
'
diff --git a/contrib/vscode/.gitattributes b/contrib/vscode/.gitattributes
new file mode 100644
index 0000000000..e89f2236ef
--- /dev/null
+++ b/contrib/vscode/.gitattributes
@@ -0,0 +1 @@
+init.sh whitespace=-indent-with-non-tab
diff --git a/contrib/vscode/README.md b/contrib/vscode/README.md
new file mode 100644
index 0000000000..8202d62035
--- /dev/null
+++ b/contrib/vscode/README.md
@@ -0,0 +1,14 @@
+Configuration for VS Code
+=========================
+
+[VS Code](https://code.visualstudio.com/) is a lightweight but powerful source
+code editor which runs on your desktop and is available for
+[Windows](https://code.visualstudio.com/docs/setup/windows),
+[macOS](https://code.visualstudio.com/docs/setup/mac) and
+[Linux](https://code.visualstudio.com/docs/setup/linux). Among other languages,
+it has [support for C/C++ via an extension](https://github.com/Microsoft/vscode-cpptools).
+
+To start developing Git with VS Code, simply run the Unix shell script called
+`init.sh` in this directory, which creates the configuration files in
+`.vscode/` that VS Code consumes. `init.sh` needs access to `make` and `gcc`,
+so run the script in a Git SDK shell if you are using Windows.
diff --git a/contrib/vscode/init.sh b/contrib/vscode/init.sh
new file mode 100755
index 0000000000..27de94994b
--- /dev/null
+++ b/contrib/vscode/init.sh
@@ -0,0 +1,375 @@
+#!/bin/sh
+
+die () {
+ echo "$*" >&2
+ exit 1
+}
+
+cd "$(dirname "$0")"/../.. ||
+die "Could not cd to top-level directory"
+
+mkdir -p .vscode ||
+die "Could not create .vscode/"
+
+# General settings
+
+cat >.vscode/settings.json.new <<\EOF ||
+{
+ "C_Cpp.intelliSenseEngine": "Default",
+ "C_Cpp.intelliSenseEngineFallback": "Disabled",
+ "[git-commit]": {
+ "editor.wordWrap": "wordWrapColumn",
+ "editor.wordWrapColumn": 72
+ },
+ "[c]": {
+ "editor.detectIndentation": false,
+ "editor.insertSpaces": false,
+ "editor.tabSize": 8,
+ "editor.wordWrap": "wordWrapColumn",
+ "editor.wordWrapColumn": 80,
+ "files.trimTrailingWhitespace": true
+ },
+ "files.associations": {
+ "*.h": "c",
+ "*.c": "c"
+ },
+ "cSpell.ignorePaths": [
+ ],
+ "cSpell.words": [
+ "DATAW",
+ "DBCACHED",
+ "DFCHECK",
+ "DTYPE",
+ "Hamano",
+ "HCAST",
+ "HEXSZ",
+ "HKEY",
+ "HKLM",
+ "IFGITLINK",
+ "IFINVALID",
+ "ISBROKEN",
+ "ISGITLINK",
+ "ISSYMREF",
+ "Junio",
+ "LPDWORD",
+ "LPPROC",
+ "LPWSTR",
+ "MSVCRT",
+ "NOARG",
+ "NOCOMPLETE",
+ "NOINHERIT",
+ "RENORMALIZE",
+ "STARTF",
+ "STARTUPINFOEXW",
+ "Schindelin",
+ "UCRT",
+ "YESNO",
+ "argcp",
+ "beginthreadex",
+ "committish",
+ "contentp",
+ "cpath",
+ "cpidx",
+ "ctim",
+ "dequote",
+ "envw",
+ "ewah",
+ "fdata",
+ "fherr",
+ "fhin",
+ "fhout",
+ "fragp",
+ "fsmonitor",
+ "hnsec",
+ "idents",
+ "includeif",
+ "interpr",
+ "iprog",
+ "isexe",
+ "iskeychar",
+ "kompare",
+ "mksnpath",
+ "mktag",
+ "mktree",
+ "mmblob",
+ "mmbuffer",
+ "mmfile",
+ "noenv",
+ "nparents",
+ "ntpath",
+ "ondisk",
+ "ooid",
+ "oplen",
+ "osdl",
+ "pnew",
+ "pold",
+ "ppinfo",
+ "pushf",
+ "pushv",
+ "rawsz",
+ "rebasing",
+ "reencode",
+ "repo",
+ "rerere",
+ "scld",
+ "sharedrepo",
+ "spawnv",
+ "spawnve",
+ "spawnvpe",
+ "strdup'ing",
+ "submodule",
+ "submodules",
+ "topath",
+ "topo",
+ "tpatch",
+ "unexecutable",
+ "unhide",
+ "unkc",
+ "unkv",
+ "unmark",
+ "unmatch",
+ "unsets",
+ "unshown",
+ "untracked",
+ "untrackedcache",
+ "unuse",
+ "upos",
+ "uval",
+ "vreportf",
+ "wargs",
+ "wargv",
+ "wbuffer",
+ "wcmd",
+ "wcsnicmp",
+ "wcstoutfdup",
+ "wdeltaenv",
+ "wdir",
+ "wenv",
+ "wenvblk",
+ "wenvcmp",
+ "wenviron",
+ "wenvpos",
+ "wenvsz",
+ "wfile",
+ "wfilename",
+ "wfopen",
+ "wfreopen",
+ "wfullpath",
+ "which'll",
+ "wlink",
+ "wmain",
+ "wmkdir",
+ "wmktemp",
+ "wnewpath",
+ "wotype",
+ "wpath",
+ "wpathname",
+ "wpgmptr",
+ "wpnew",
+ "wpointer",
+ "wpold",
+ "wpos",
+ "wputenv",
+ "wrmdir",
+ "wship",
+ "wtarget",
+ "wtemplate",
+ "wunlink",
+ "xcalloc",
+ "xgetcwd",
+ "xmallocz",
+ "xmemdupz",
+ "xmmap",
+ "xopts",
+ "xrealloc",
+ "xsnprintf",
+ "xutftowcs",
+ "xutftowcsn",
+ "xwcstoutf"
+ ],
+ "cSpell.ignoreRegExpList": [
+ "\\\"(DIRC|FSMN|REUC|UNTR)\\\"",
+ "\\\\u[0-9a-fA-Fx]{4}\\b",
+ "\\b(filfre|frotz|xyzzy)\\b",
+ "\\bCMIT_FMT_DEFAULT\\b",
+ "\\bde-munge\\b",
+ "\\bGET_OID_DISAMBIGUATORS\\b",
+ "\\bHASH_RENORMALIZE\\b",
+ "\\bTREESAMEness\\b",
+ "\\bUSE_STDEV\\b",
+ "\\Wchar *\\*\\W*utfs\\W",
+ "cURL's",
+ "nedmalloc'ed",
+ "ntifs\\.h",
+ ],
+}
+EOF
+die "Could not write settings.json"
+
+# Infer some setup-specific locations/names
+
+GCCPATH="$(which gcc)"
+GDBPATH="$(which gdb)"
+MAKECOMMAND="make -j5 DEVELOPER=1"
+OSNAME=
+X=
+case "$(uname -s)" in
+MINGW*)
+ GCCPATH="$(cygpath -am "$GCCPATH")"
+ GDBPATH="$(cygpath -am "$GDBPATH")"
+ MAKE_BASH="$(cygpath -am /git-cmd.exe) --command=usr\\\\bin\\\\bash.exe"
+ MAKECOMMAND="$MAKE_BASH -lc \\\"$MAKECOMMAND\\\""
+ OSNAME=Win32
+ X=.exe
+ ;;
+Linux)
+ OSNAME=Linux
+ ;;
+Darwin)
+ OSNAME=macOS
+ ;;
+esac
+
+# Default build task
+
+cat >.vscode/tasks.json.new <<EOF ||
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "make",
+ "type": "shell",
+ "command": "$MAKECOMMAND",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
+EOF
+die "Could not install default build task"
+
+# Debugger settings
+
+cat >.vscode/launch.json.new <<EOF ||
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit:
+ // https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "(gdb) Launch",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "\${workspaceFolder}/git$X",
+ "args": [],
+ "stopAtEntry": false,
+ "cwd": "\${workspaceFolder}",
+ "environment": [],
+ "externalConsole": true,
+ "MIMode": "gdb",
+ "miDebuggerPath": "$GDBPATH",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
+ ]
+ }
+ ]
+}
+EOF
+die "Could not write launch configuration"
+
+# C/C++ extension settings
+
+make -f - OSNAME=$OSNAME GCCPATH="$GCCPATH" vscode-init \
+ >.vscode/c_cpp_properties.json <<\EOF ||
+include Makefile
+
+vscode-init:
+ @mkdir -p .vscode && \
+ incs= && defs= && \
+ for e in $(ALL_CFLAGS) \
+ '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
+ '-DGIT_LOCALE_PATH="$(localedir_relative_SQ)"' \
+ '-DBINDIR="$(bindir_relative_SQ)"' \
+ '-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"' \
+ '-DDEFAULT_GIT_TEMPLATE_DIR="$(template_dir_SQ)"' \
+ '-DETC_GITCONFIG="$(ETC_GITCONFIG_SQ)"' \
+ '-DETC_GITATTRIBUTES="$(ETC_GITATTRIBUTES_SQ)"' \
+ '-DGIT_LOCALE_PATH="$(localedir_relative_SQ)"' \
+ '-DCURL_DISABLE_TYPECHECK', \
+ '-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
+ '-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
+ '-DGIT_INFO_PATH="$(infodir_relative_SQ)"'; do \
+ case "$$e" in \
+ -I.) \
+ incs="$$(printf '% 16s"$${workspaceRoot}",\n%s' \
+ "" "$$incs")" \
+ ;; \
+ -I/*) \
+ incs="$$(printf '% 16s"%s",\n%s' \
+ "" "$${e#-I}" "$$incs")" \
+ ;; \
+ -I*) \
+ incs="$$(printf '% 16s"$${workspaceRoot}/%s",\n%s' \
+ "" "$${e#-I}" "$$incs")" \
+ ;; \
+ -D*) \
+ defs="$$(printf '% 16s"%s",\n%s' \
+ "" "$$(echo "$${e#-D}" | sed 's/"/\\&/g')" \
+ "$$defs")" \
+ ;; \
+ esac; \
+ done && \
+ echo '{' && \
+ echo ' "configurations": [' && \
+ echo ' {' && \
+ echo ' "name": "$(OSNAME)",' && \
+ echo ' "intelliSenseMode": "clang-x64",' && \
+ echo ' "includePath": [' && \
+ echo "$$incs" | sort | sed '$$s/,$$//' && \
+ echo ' ],' && \
+ echo ' "defines": [' && \
+ echo "$$defs" | sort | sed '$$s/,$$//' && \
+ echo ' ],' && \
+ echo ' "browse": {' && \
+ echo ' "limitSymbolsToIncludedHeaders": true,' && \
+ echo ' "databaseFilename": "",' && \
+ echo ' "path": [' && \
+ echo ' "$${workspaceRoot}"' && \
+ echo ' ]' && \
+ echo ' },' && \
+ echo ' "cStandard": "c11",' && \
+ echo ' "cppStandard": "c++17",' && \
+ echo ' "compilerPath": "$(GCCPATH)"' && \
+ echo ' }' && \
+ echo ' ],' && \
+ echo ' "version": 4' && \
+ echo '}'
+EOF
+die "Could not write settings for the C/C++ extension"
+
+for file in .vscode/settings.json .vscode/tasks.json .vscode/launch.json
+do
+ if test -f $file
+ then
+ if git diff --no-index --quiet --exit-code $file $file.new
+ then
+ rm $file.new
+ else
+ printf "The file $file.new has these changes:\n\n"
+ git --no-pager diff --no-index $file $file.new
+ printf "\n\nMaybe \`mv $file.new $file\`?\n\n"
+ fi
+ else
+ mv $file.new $file
+ fi
+done