aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Documentation/RelNotes/1.9.txt18
-rw-r--r--Documentation/SubmittingPatches11
-rw-r--r--Documentation/config.txt4
-rw-r--r--Documentation/fetch-options.txt26
-rw-r--r--Documentation/git-cherry.txt143
-rw-r--r--Documentation/git-fetch.txt14
-rw-r--r--Documentation/git-lost-found.txt74
-rw-r--r--Documentation/git-peek-remote.txt43
-rw-r--r--Documentation/git-repo-config.txt23
-rw-r--r--Documentation/git-tar-tree.txt82
-rw-r--r--Documentation/gitignore.txt19
-rw-r--r--Documentation/technical/api-remote.txt20
-rw-r--r--Documentation/technical/protocol-capabilities.txt31
-rw-r--r--Makefile6
-rw-r--r--builtin.h1
-rw-r--r--builtin/config.c6
-rw-r--r--builtin/fetch.c298
-rw-r--r--builtin/get-tar-commit-id.c40
-rw-r--r--builtin/remote.c196
-rw-r--r--builtin/tar-tree.c102
-rw-r--r--command-list.txt4
-rw-r--r--commit-slab.h39
-rwxr-xr-x[-rw-r--r--]compat/vcbuild/scripts/clink.pl0
-rwxr-xr-x[-rw-r--r--]compat/vcbuild/scripts/lib.pl0
-rw-r--r--config.c19
-rwxr-xr-x[-rw-r--r--]contrib/buildsystems/engine.pl0
-rwxr-xr-x[-rw-r--r--]contrib/buildsystems/generate0
-rwxr-xr-x[-rw-r--r--]contrib/buildsystems/parse.pl0
-rw-r--r--contrib/completion/git-completion.bash6
-rw-r--r--contrib/completion/git-completion.tcsh2
-rwxr-xr-xcontrib/examples/git-whatchanged.sh4
-rwxr-xr-xcontrib/hooks/post-receive-email1
-rwxr-xr-x[-rw-r--r--]contrib/hooks/pre-auto-gc-battery1
-rwxr-xr-x[-rw-r--r--]contrib/hooks/setgitperms.perl0
-rwxr-xr-x[-rw-r--r--]contrib/hooks/update-paranoid0
-rw-r--r--contrib/p4import/README1
-rw-r--r--contrib/p4import/git-p4import.py365
-rw-r--r--contrib/p4import/git-p4import.txt167
-rw-r--r--git-gui/Makefile2
-rwxr-xr-xgit-gui/git-gui.sh47
-rw-r--r--git-gui/lib/blame.tcl2
-rw-r--r--git-gui/lib/choose_repository.tcl12
-rw-r--r--git-gui/lib/index.tcl2
-rw-r--r--git-gui/lib/option.tcl2
-rw-r--r--git-gui/lib/spellcheck.tcl4
-rw-r--r--git-gui/macosx/Info.plist2
-rwxr-xr-xgit-lost-found.sh33
-rw-r--r--git-mergetool--lib.sh3
-rwxr-xr-xgit-p4.py2
-rw-r--r--git-parse-remote.sh4
-rwxr-xr-xgit-pull.sh2
-rw-r--r--git-rebase--am.sh3
-rw-r--r--git-rebase--interactive.sh9
-rw-r--r--git-rebase--merge.sh4
-rw-r--r--git-sh-i18n.sh5
-rw-r--r--git-sh-setup.sh9
-rw-r--r--git.c3
-rwxr-xr-xgitk-git/gitk563
-rw-r--r--remote.c94
-rw-r--r--remote.h8
-rw-r--r--send-pack.c2
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/00compile.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/add_path_to_url.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/can_compress.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/canonicalize_url.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/collapse_dotdot.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/fatal.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/join_paths.t0
-rw-r--r--t/gitweb-lib.sh3
-rw-r--r--t/lib-bash.sh7
-rw-r--r--t/lib-cvs.sh2
-rw-r--r--t/lib-diff-alternative.sh3
-rw-r--r--t/lib-gettext.sh3
-rw-r--r--t/lib-git-daemon.sh18
-rw-r--r--t/lib-httpd.sh29
-rw-r--r--t/lib-pack.sh2
-rw-r--r--t/lib-pager.sh2
-rw-r--r--t/lib-prereq-FILEMODE.sh11
-rw-r--r--t/lib-read-tree.sh2
-rw-r--r--t/lib-rebase.sh2
-rw-r--r--t/lib-terminal.sh2
-rw-r--r--t/perf/perf-lib.sh4
-rwxr-xr-x[-rw-r--r--]t/t0202/test.pl0
-rwxr-xr-xt/t1303-wacky-config.sh64
-rwxr-xr-xt/t3701-add-interactive.sh1
-rwxr-xr-xt/t4102-apply-rename.sh1
-rwxr-xr-xt/t4116-apply-reverse.sh4
-rwxr-xr-xt/t4120-apply-popt.sh1
-rwxr-xr-xt/t4129-apply-samemode.sh1
-rwxr-xr-xt/t5000-tar-tree.sh36
-rwxr-xr-xt/t5001-archive-attr.sh10
-rwxr-xr-xt/t5510-fetch.sh36
-rw-r--r--t/t5515/fetch.br-unconfig_--tags_.._.git1
-rw-r--r--t/t5515/fetch.master_--tags_.._.git1
-rwxr-xr-xt/t5525-fetch-tagopt.sh23
-rwxr-xr-xt/t5536-fetch-conflicts.sh100
-rwxr-xr-xt/t6031-merge-recursive.sh1
-rwxr-xr-x[-rw-r--r--]t/t9150/make-svk-dump0
-rwxr-xr-x[-rw-r--r--]t/t9151/make-svnmerge-dump0
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh1
-rw-r--r--t/test-lib-functions.sh3
-rw-r--r--t/test-lib.sh12
103 files changed, 1338 insertions, 1635 deletions
diff --git a/.gitignore b/.gitignore
index a78367c17..b5f9defed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,7 +76,6 @@
/git-init-db
/git-instaweb
/git-log
-/git-lost-found
/git-ls-files
/git-ls-remote
/git-ls-tree
@@ -106,7 +105,6 @@
/git-pack-refs
/git-parse-remote
/git-patch-id
-/git-peek-remote
/git-prune
/git-prune-packed
/git-pull
@@ -132,7 +130,6 @@
/git-remote-testsvn
/git-repack
/git-replace
-/git-repo-config
/git-request-pull
/git-rerere
/git-reset
@@ -160,7 +157,6 @@
/git-svn
/git-symbolic-ref
/git-tag
-/git-tar-tree
/git-unpack-file
/git-unpack-objects
/git-update-index
diff --git a/Documentation/RelNotes/1.9.txt b/Documentation/RelNotes/1.9.txt
index 9debcc41e..7120c220e 100644
--- a/Documentation/RelNotes/1.9.txt
+++ b/Documentation/RelNotes/1.9.txt
@@ -15,6 +15,13 @@ Read-only support for experimental loose-object format, in which users
could optionally choose to write in their loose objects for a short
while between v1.4.3 to v1.5.3 era, has been dropped.
+The meanings of "--tags" option to "git fetch" has changed; the
+command fetches tags _in addition to_ what are fetched by the same
+command line without the option.
+
+A handful of ancient commands that have long been deprecated are
+finally gone (repo-config, tar-tree, lost-found, and peek-remote).
+
Backward compatibility notes (for Git 2.0)
------------------------------------------
@@ -68,7 +75,7 @@ Updates since v1.8.5
Foreign interfaces, subsystems and ports.
- * The HTTP transport, when talking GSS-Negotinate, uses "100
+ * The HTTP transport, when talking GSS-Negotiate, uses "100
Continue" response to avoid having to rewind and resend a large
payload, which may not be always doable.
@@ -91,6 +98,10 @@ UI, Workflows & Features
* "git rev-parse --parseopt" learned a new "--stuck-long" option to
help scripts parse options with an optional parameter.
+ * The "--tags" option to "git fetch" no longer tells the command to
+ fetch _only_ the tags. It instead fetches tags _in addition to_
+ what are fetched by the same command line without the option.
+
Performance, Internal Implementation, etc.
@@ -103,6 +114,11 @@ Performance, Internal Implementation, etc.
point out of the reflog entries for the remote-tracking branch the
work has been based on.
+ * A third-party "receive-pack" (the responder to "git push") can
+ advertise the "no-thin" capability to tell "git push" not to use
+ the thin-pack optimization. Our receive-pack has always been
+ capable of accepting and fattening a thin-pack, and will continue
+ not to ask "git push" to use a non-thin pack.
Also contains various documentation updates and code clean-ups.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 705557689..e6d46edbe 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -139,8 +139,15 @@ People on the Git mailing list need to be able to read and
comment on the changes you are submitting. It is important for
a developer to be able to "quote" your changes, using standard
e-mail tools, so that they may comment on specific portions of
-your code. For this reason, all patches should be submitted
-"inline". If your log message (including your name on the
+your code. For this reason, each patch should be submitted
+"inline" in a separate message.
+
+Multiple related patches should be grouped into their own e-mail
+thread to help readers find all parts of the series. To that end,
+send them as replies to either an additional "cover letter" message
+(see below), the first patch, or the respective preceding patch.
+
+If your log message (including your name on the
Signed-off-by line) is not writable in ASCII, make sure that
you send off a message in the correct encoding.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index ab26963d6..a4058063c 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2087,8 +2087,8 @@ remote.<name>.vcs::
remote.<name>.prune::
When set to true, fetching from this remote by default will also
- remove any remote-tracking branches which no longer exist on the
- remote (as if the `--prune` option was give on the command line).
+ remove any remote-tracking references that no longer exist on the
+ remote (as if the `--prune` option was given on the command line).
Overrides `fetch.prune` settings, if any.
remotes.<group>::
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index ba1fe4958..f0ef7d02a 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -41,17 +41,20 @@ ifndef::git-pull[]
-p::
--prune::
- After fetching, remove any remote-tracking branches which
- no longer exist on the remote.
+ After fetching, remove any remote-tracking references that no
+ longer exist on the remote. Tags are not subject to pruning
+ if they are fetched only because of the default tag
+ auto-following or due to a --tags option. However, if tags
+ are fetched due to an explicit refspec (either on the command
+ line or in the remote configuration, for example if the remote
+ was cloned with the --mirror option), then they are also
+ subject to pruning.
endif::git-pull[]
-ifdef::git-pull[]
---no-tags::
-endif::git-pull[]
ifndef::git-pull[]
-n::
---no-tags::
endif::git-pull[]
+--no-tags::
By default, tags that point at objects that are downloaded
from the remote repository are fetched and stored locally.
This option disables this automatic tag following. The default
@@ -61,11 +64,12 @@ endif::git-pull[]
ifndef::git-pull[]
-t::
--tags::
- This is a short-hand for giving `refs/tags/*:refs/tags/*`
- refspec from the command line, to ask all tags to be fetched
- and stored locally. Because this acts as an explicit
- refspec, the default refspecs (configured with the
- remote.$name.fetch variable) are overridden and not used.
+ Fetch all tags from the remote (i.e., fetch remote tags
+ `refs/tags/*` into local tags with the same name), in addition
+ to whatever else would otherwise be fetched. Using this
+ option alone does not subject tags to pruning, even if --prune
+ is used (though tags may be pruned anyway if they are also the
+ destination of an explicit refspec; see '--prune').
--recurse-submodules[=yes|on-demand|no]::
This option controls if and under what conditions new commits of
diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt
index 2d0daae62..0ea921a59 100644
--- a/Documentation/git-cherry.txt
+++ b/Documentation/git-cherry.txt
@@ -3,7 +3,7 @@ git-cherry(1)
NAME
----
-git-cherry - Find commits not merged upstream
+git-cherry - Find commits yet to be applied to upstream
SYNOPSIS
--------
@@ -12,46 +12,26 @@ SYNOPSIS
DESCRIPTION
-----------
-The changeset (or "diff") of each commit between the fork-point and <head>
-is compared against each commit between the fork-point and <upstream>.
-The diffs are compared after removing any whitespace and line numbers.
+Determine whether there are commits in `<head>..<upstream>` that are
+equivalent to those in the range `<limit>..<head>`.
-Every commit that doesn't exist in the <upstream> branch
-has its id (sha1) reported, prefixed by a symbol. The ones that have
-equivalent change already
-in the <upstream> branch are prefixed with a minus (-) sign, and those
-that only exist in the <head> branch are prefixed with a plus (+) symbol:
-
- __*__*__*__*__> <upstream>
- /
- fork-point
- \__+__+__-__+__+__-__+__> <head>
-
-
-If a <limit> has been given then the commits along the <head> branch up
-to and including <limit> are not reported:
-
- __*__*__*__*__> <upstream>
- /
- fork-point
- \__*__*__<limit>__-__+__> <head>
-
-
-Because 'git cherry' compares the changeset rather than the commit id
-(sha1), you can use 'git cherry' to find out if a commit you made locally
-has been applied <upstream> under a different commit id. For example,
-this will happen if you're feeding patches <upstream> via email rather
-than pushing or pulling commits directly.
+The equivalence test is based on the diff, after removing whitespace
+and line numbers. git-cherry therefore detects when commits have been
+"copied" by means of linkgit:git-cherry-pick[1], linkgit:git-am[1] or
+linkgit:git-rebase[1].
+Outputs the SHA1 of every commit in `<limit>..<head>`, prefixed with
+`-` for commits that have an equivalent in <upstream>, and `+` for
+commits that do not.
OPTIONS
-------
-v::
- Verbose.
+ Show the commit subjects next to the SHA1s.
<upstream>::
- Upstream branch to compare against.
- Defaults to the first tracked remote branch, if available.
+ Upstream branch to search for equivalent commits.
+ Defaults to the upstream branch of HEAD.
<head>::
Working branch; defaults to HEAD.
@@ -59,6 +39,103 @@ OPTIONS
<limit>::
Do not report commits up to (and including) limit.
+EXAMPLES
+--------
+
+Patch workflows
+~~~~~~~~~~~~~~~
+
+git-cherry is frequently used in patch-based workflows (see
+linkgit:gitworkflows[7]) to determine if a series of patches has been
+applied by the upstream maintainer. In such a workflow you might
+create and send a topic branch like this:
+
+------------
+$ git checkout -b topic origin/master
+# work and create some commits
+$ git format-patch origin/master
+$ git send-email ... 00*
+------------
+
+Later, you can see whether your changes have been applied by saying
+(still on `topic`):
+
+------------
+$ git fetch # update your notion of origin/master
+$ git cherry -v
+------------
+
+Concrete example
+~~~~~~~~~~~~~~~~
+
+In a situation where topic consisted of three commits, and the
+maintainer applied two of them, the situation might look like:
+
+------------
+$ git log --graph --oneline --decorate --boundary origin/master...topic
+* 7654321 (origin/master) upstream tip commit
+[... snip some other commits ...]
+* cccc111 cherry-pick of C
+* aaaa111 cherry-pick of A
+[... snip a lot more that has happened ...]
+| * cccc000 (topic) commit C
+| * bbbb000 commit B
+| * aaaa000 commit A
+|/
+o 1234567 branch point
+------------
+
+In such cases, git-cherry shows a concise summary of what has yet to
+be applied:
+
+------------
+$ git cherry origin/master topic
+- cccc000... commit C
++ bbbb000... commit B
+- aaaa000... commit A
+------------
+
+Here, we see that the commits A and C (marked with `-`) can be
+dropped from your `topic` branch when you rebase it on top of
+`origin/master`, while the commit B (marked with `+`) still needs to
+be kept so that it will be sent to be applied to `origin/master`.
+
+
+Using a limit
+~~~~~~~~~~~~~
+
+The optional <limit> is useful in cases where your topic is based on
+other work that is not in upstream. Expanding on the previous
+example, this might look like:
+
+------------
+$ git log --graph --oneline --decorate --boundary origin/master...topic
+* 7654321 (origin/master) upstream tip commit
+[... snip some other commits ...]
+* cccc111 cherry-pick of C
+* aaaa111 cherry-pick of A
+[... snip a lot more that has happened ...]
+| * cccc000 (topic) commit C
+| * bbbb000 commit B
+| * aaaa000 commit A
+| * 0000fff (base) unpublished stuff F
+[... snip ...]
+| * 0000aaa unpublished stuff A
+|/
+o 1234567 merge-base between upstream and topic
+------------
+
+By specifying `base` as the limit, you can avoid listing commits
+between `base` and `topic`:
+
+------------
+$ git cherry origin/master topic base
+- cccc000... commit C
++ bbbb000... commit B
+- aaaa000... commit A
+------------
+
+
SEE ALSO
--------
linkgit:git-patch-id[1]
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index a7b245d94..5809aa4eb 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -24,13 +24,13 @@ The ref names and their object names of fetched refs are stored
in `.git/FETCH_HEAD`. This information is left for a later merge
operation done by 'git merge'.
-When <refspec> stores the fetched result in remote-tracking branches,
-the tags that point at these branches are automatically
-followed. This is done by first fetching from the remote using
-the given <refspec>s, and if the repository has objects that are
-pointed by remote tags that it does not yet have, then fetch
-those missing tags. If the other end has tags that point at
-branches you are not interested in, you will not get them.
+By default, tags are auto-followed. This means that when fetching
+from a remote, any tags on the remote that point to objects that exist
+in the local repository are fetched. The effect is to fetch tags that
+point at branches that you are interested in. This default behavior
+can be changed by using the --tags or --no-tags options, by
+configuring remote.<name>.tagopt, or by using a refspec that fetches
+tags explicitly.
'git fetch' can fetch from either a single named repository,
or from several repositories at once if <group> is given and
diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt
deleted file mode 100644
index d54932889..000000000
--- a/Documentation/git-lost-found.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-git-lost-found(1)
-=================
-
-NAME
-----
-git-lost-found - Recover lost refs that luckily have not yet been pruned
-
-SYNOPSIS
---------
-[verse]
-'git lost-found'
-
-DESCRIPTION
------------
-
-*NOTE*: this command is deprecated. Use linkgit:git-fsck[1] with
-the option '--lost-found' instead.
-
-Finds dangling commits and tags from the object database, and
-creates refs to them in the .git/lost-found/ directory. Commits and
-tags that dereference to commits are stored in .git/lost-found/commit,
-and other objects are stored in .git/lost-found/other.
-
-
-OUTPUT
-------
-Prints to standard output the object names and one-line descriptions
-of any commits or tags found.
-
-EXAMPLE
--------
-
-Suppose you run 'git tag -f' and mistype the tag to overwrite.
-The ref to your tag is overwritten, but until you run 'git
-prune', the tag itself is still there.
-
-------------
-$ git lost-found
-[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
-...
-------------
-
-Also you can use gitk to browse how any tags found relate to each
-other.
-
-------------
-$ gitk $(cd .git/lost-found/commit && echo ??*)
-------------
-
-After making sure you know which the object is the tag you are looking
-for, you can reconnect it to your regular `refs` hierarchy by using
-the `update-ref` command.
-
-------------
-$ git cat-file -t 1ef2b196
-tag
-$ git cat-file tag 1ef2b196
-object fa41bbce8e38c67a218415de6cfa510c7e50032a
-type commit
-tag v0.99.9c
-tagger Junio C Hamano <junkio@cox.net> 1131059594 -0800
-
-GIT 0.99.9c
-
-This contains the following changes from the "master" branch, since
-...
-$ git update-ref refs/tags/not-lost-anymore 1ef2b196
-$ git rev-parse not-lost-anymore
-1ef2b196d909eed523d4f3c9bf54b78cdd6843c6
-------------
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt
deleted file mode 100644
index 87ea3fb05..000000000
--- a/Documentation/git-peek-remote.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-git-peek-remote(1)
-==================
-
-NAME
-----
-git-peek-remote - List the references in a remote repository
-
-
-SYNOPSIS
---------
-[verse]
-'git peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
-
-DESCRIPTION
------------
-This command is deprecated; use 'git ls-remote' instead.
-
-OPTIONS
--------
---upload-pack=<git-upload-pack>::
- Use this to specify the path to 'git-upload-pack' on the
- remote side, if it is not found on your $PATH. Some
- installations of sshd ignores the user's environment
- setup scripts for login shells (e.g. .bash_profile) and
- your privately installed git may not be found on the system
- default $PATH. Another workaround suggested is to set
- up your $PATH in ".bashrc", but this flag is for people
- who do not want to pay the overhead for non-interactive
- shells, but prefer having a lean .bashrc file (they set most of
- the things up in .bash_profile).
-
-<host>::
- A remote host that houses the repository. When this
- part is specified, 'git-upload-pack' is invoked via
- ssh.
-
-<directory>::
- The repository to sync from.
-
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
deleted file mode 100644
index 9ec115b9e..000000000
--- a/Documentation/git-repo-config.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-git-repo-config(1)
-==================
-
-NAME
-----
-git-repo-config - Get and set repository or global options
-
-
-SYNOPSIS
---------
-[verse]
-'git repo-config' ...
-
-
-DESCRIPTION
------------
-
-This is a synonym for linkgit:git-config[1]. Please refer to the
-documentation of that command.
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt
deleted file mode 100644
index f7362dc2d..000000000
--- a/Documentation/git-tar-tree.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-git-tar-tree(1)
-===============
-
-NAME
-----
-git-tar-tree - Create a tar archive of the files in the named tree object
-
-
-SYNOPSIS
---------
-[verse]
-'git tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
-
-DESCRIPTION
------------
-THIS COMMAND IS DEPRECATED. Use 'git archive' with `--format=tar`
-option instead (and move the <base> argument to `--prefix=base/`).
-
-Creates a tar archive containing the tree structure for the named tree.
-When <base> is specified it is added as a leading path to the files in the
-generated tar archive.
-
-'git tar-tree' behaves differently when given a tree ID versus when given
-a commit ID or tag ID. In the first case the current time is used as
-modification time of each file in the archive. In the latter case the
-commit time as recorded in the referenced commit object is used instead.
-Additionally the commit ID is stored in a global extended pax header.
-It can be extracted using 'git get-tar-commit-id'.
-
-OPTIONS
--------
-
-<tree-ish>::
- The tree or commit to produce tar archive for. If it is
- the object name of a commit object.
-
-<base>::
- Leading path to the files in the resulting tar archive.
-
---remote=<repo>::
- Instead of making a tar archive from local repository,
- retrieve a tar archive from a remote repository.
-
-CONFIGURATION
--------------
-
-tar.umask::
- This variable can be used to restrict the permission bits of
- tar archive entries. The default is 0002, which turns off the
- world write bit. The special value "user" indicates that the
- archiving user's umask will be used instead. See umask(2) for
- details.
-
-EXAMPLES
---------
-`git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -)`::
-
- Create a tar archive that contains the contents of the
- latest commit on the current branch, and extracts it in
- `/var/tmp/junk` directory.
-
-`git tar-tree v1.4.0 git-1.4.0 | gzip >git-1.4.0.tar.gz`::
-
- Create a tarball for v1.4.0 release.
-
-`git tar-tree v1.4.0^{tree} git-1.4.0 | gzip >git-1.4.0.tar.gz`::
-
- Create a tarball for v1.4.0 release, but without a
- global extended pax header.
-
-`git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar`::
-
- Get a tarball v1.4.0 from example.com.
-
-`git tar-tree HEAD:Documentation/ git-docs > git-1.4.0-docs.tar`::
-
- Put everything in the current head's Documentation/ directory
- into 'git-1.4.0-docs.tar', with the prefix 'git-docs/'.
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index f97196051..205e80ef8 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -79,8 +79,10 @@ PATTERN FORMAT
- An optional prefix "`!`" which negates the pattern; any
matching file excluded by a previous pattern will become
- included again. If a negated pattern matches, this will
- override lower precedence patterns sources.
+ included again. It is not possible to re-include a file if a parent
+ directory of that file is excluded. Git doesn't list excluded
+ directories for performance reasons, so any patterns on contained
+ files have no effect, no matter where they are defined.
Put a backslash ("`\`") in front of the first "`!`" for patterns
that begin with a literal "`!`", for example, "`\!important!.txt`".
@@ -182,6 +184,19 @@ Another example:
The second .gitignore prevents Git from ignoring
`arch/foo/kernel/vmlinux.lds.S`.
+Example to exclude everything except a specific directory `foo/bar`
+(note the `/*` - without the slash, the wildcard would also exclude
+everything within `foo/bar`):
+
+--------------------------------------------------------------
+ $ cat .gitignore
+ # exclude everything except directory foo/bar
+ /*
+ !/foo
+ /foo/*
+ !/foo/bar
+--------------------------------------------------------------
+
SEE ALSO
--------
linkgit:git-rm[1],
diff --git a/Documentation/technical/api-remote.txt b/Documentation/technical/api-remote.txt
index 4be87768f..5d245aa9d 100644
--- a/Documentation/technical/api-remote.txt
+++ b/Documentation/technical/api-remote.txt
@@ -58,16 +58,16 @@ default remote, given the current branch and configuration.
struct refspec
--------------
-A struct refspec holds the parsed interpretation of a refspec. If it
-will force updates (starts with a '+'), force is true. If it is a
-pattern (sides end with '*') pattern is true. src and dest are the two
-sides (if a pattern, only the part outside of the wildcards); if there
-is only one side, it is src, and dst is NULL; if sides exist but are
-empty (i.e., the refspec either starts or ends with ':'), the
-corresponding side is "".
-
-This parsing can be done to an array of strings to give an array of
-struct refpsecs with parse_ref_spec().
+A struct refspec holds the parsed interpretation of a refspec. If it
+will force updates (starts with a '+'), force is true. If it is a
+pattern (sides end with '*') pattern is true. src and dest are the
+two sides (including '*' characters if present); if there is only one
+side, it is src, and dst is NULL; if sides exist but are empty (i.e.,
+the refspec either starts or ends with ':'), the corresponding side is
+"".
+
+An array of strings can be parsed into an array of struct refspecs
+using parse_fetch_refspec() or parse_push_refspec().
remote_find_tracking(), given a remote and a struct refspec with
either src or dst filled out, will fill out the other such that the
diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt
index fd8ffa5df..e3e792476 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -72,14 +72,29 @@ interleaved with S-R-Q.
thin-pack
---------
-This capability means that the server can send a 'thin' pack, a pack
-which does not contain base objects; if those base objects are available
-on client side. Client requests 'thin-pack' capability when it
-understands how to "thicken" it by adding required delta bases making
-it self-contained.
-
-Client MUST NOT request 'thin-pack' capability if it cannot turn a thin
-pack into a self-contained pack.
+A thin pack is one with deltas which reference base objects not
+contained within the pack (but are known to exist at the receiving
+end). This can reduce the network traffic significantly, but it
+requires the receiving end to know how to "thicken" these packs by
+adding the missing bases to the pack.
+
+The upload-pack server advertises 'thin-pack' when it can generate
+and send a thin pack. A client requests the 'thin-pack' capability
+when it understands how to "thicken" it, notifying the server that
+it can receive such a pack. A client MUST NOT request the
+'thin-pack' capability if it cannot turn a thin pack into a
+self-contained pack.
+
+Receive-pack, on the other hand, is assumed by default to be able to
+handle thin packs, but can ask the client not to use the feature by
+advertising the 'no-thin' capability. A client MUST NOT send a thin
+pack if the server advertises the 'no-thin' capability.
+
+The reasons for this asymmetry are historical. The receive-pack
+program did not exist until after the invention of thin packs, so
+historically the reference implementation of receive-pack always
+understood thin packs. Adding 'no-thin' later allowed receive-pack
+to disable the feature in a backwards-compatible manner.
side-band, side-band-64k
diff --git a/Makefile b/Makefile
index 67f175490..b4af1e205 100644
--- a/Makefile
+++ b/Makefile
@@ -452,7 +452,6 @@ SCRIPT_SH += git-am.sh
SCRIPT_SH += git-bisect.sh
SCRIPT_SH += git-difftool--helper.sh
SCRIPT_SH += git-filter-branch.sh
-SCRIPT_SH += git-lost-found.sh
SCRIPT_SH += git-merge-octopus.sh
SCRIPT_SH += git-merge-one-file.sh
SCRIPT_SH += git-merge-resolve.sh
@@ -587,11 +586,8 @@ BUILT_INS += git-cherry$X
BUILT_INS += git-cherry-pick$X
BUILT_INS += git-format-patch$X
BUILT_INS += git-fsck-objects$X
-BUILT_INS += git-get-tar-commit-id$X
BUILT_INS += git-init$X
BUILT_INS += git-merge-subtree$X
-BUILT_INS += git-peek-remote$X
-BUILT_INS += git-repo-config$X
BUILT_INS += git-show$X
BUILT_INS += git-stage$X
BUILT_INS += git-status$X
@@ -932,6 +928,7 @@ BUILTIN_OBJS += builtin/fmt-merge-msg.o
BUILTIN_OBJS += builtin/for-each-ref.o
BUILTIN_OBJS += builtin/fsck.o
BUILTIN_OBJS += builtin/gc.o
+BUILTIN_OBJS += builtin/get-tar-commit-id.o
BUILTIN_OBJS += builtin/grep.o
BUILTIN_OBJS += builtin/hash-object.o
BUILTIN_OBJS += builtin/help.o
@@ -983,7 +980,6 @@ BUILTIN_OBJS += builtin/show-ref.o
BUILTIN_OBJS += builtin/stripspace.o
BUILTIN_OBJS += builtin/symbolic-ref.o
BUILTIN_OBJS += builtin/tag.o
-BUILTIN_OBJS += builtin/tar-tree.o
BUILTIN_OBJS += builtin/unpack-file.o
BUILTIN_OBJS += builtin/unpack-objects.o
BUILTIN_OBJS += builtin/update-index.o
diff --git a/builtin.h b/builtin.h
index b56cf07ab..d4afbfe41 100644
--- a/builtin.h
+++ b/builtin.h
@@ -103,7 +103,6 @@ extern int cmd_remote(int argc, const char **argv, const char *prefix);
extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
extern int cmd_repack(int argc, const char **argv, const char *prefix);
-extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
extern int cmd_rerere(int argc, const char **argv, const char *prefix);
extern int cmd_reset(int argc, const char **argv, const char *prefix);
extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
diff --git a/builtin/config.c b/builtin/config.c
index 20e89fe4e..92ebf23f0 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -671,9 +671,3 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return 0;
}
-
-int cmd_repo_config(int argc, const char **argv, const char *prefix)
-{
- fprintf(stderr, "WARNING: git repo-config is deprecated in favor of git config.\n");
- return cmd_config(argc, argv, prefix);
-}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index bd7a10164..3d978eb58 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -160,48 +160,156 @@ static void add_merge_config(struct ref **head,
}
}
+static int add_existing(const char *refname, const unsigned char *sha1,
+ int flag, void *cbdata)
+{
+ struct string_list *list = (struct string_list *)cbdata;
+ struct string_list_item *item = string_list_insert(list, refname);
+ item->util = xmalloc(20);
+ hashcpy(item->util, sha1);
+ return 0;
+}
+
+static int will_fetch(struct ref **head, const unsigned char *sha1)
+{
+ struct ref *rm = *head;
+ while (rm) {
+ if (!hashcmp(rm->old_sha1, sha1))
+ return 1;
+ rm = rm->next;
+ }
+ return 0;
+}
+
static void find_non_local_tags(struct transport *transport,
struct ref **head,
- struct ref ***tail);
+ struct ref ***tail)
+{
+ struct string_list existing_refs = STRING_LIST_INIT_DUP;
+ struct string_list remote_refs = STRING_LIST_INIT_NODUP;
+ const struct ref *ref;
+ struct string_list_item *item = NULL;
+
+ for_each_ref(add_existing, &existing_refs);
+ for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
+ if (prefixcmp(ref->name, "refs/tags/"))
+ continue;
+
+ /*
+ * The peeled ref always follows the matching base
+ * ref, so if we see a peeled ref that we don't want
+ * to fetch then we can mark the ref entry in the list
+ * as one to ignore by setting util to NULL.
+ */
+ if (!suffixcmp(ref->name, "^{}")) {
+ if (item && !has_sha1_file(ref->old_sha1) &&
+ !will_fetch(head, ref->old_sha1) &&
+ !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+ item = NULL;
+ continue;
+ }
+
+ /*
+ * If item is non-NULL here, then we previously saw a
+ * ref not followed by a peeled reference, so we need
+ * to check if it is a lightweight tag that we want to
+ * fetch.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+
+ item = NULL;
+
+ /* skip duplicates and refs that we already have */
+ if (string_list_has_string(&remote_refs, ref->name) ||
+ string_list_has_string(&existing_refs, ref->name))
+ continue;
+
+ item = string_list_insert(&remote_refs, ref->name);
+ item->util = (void *)ref->old_sha1;
+ }
+ string_list_clear(&existing_refs, 1);
+
+ /*
+ * We may have a final lightweight tag that needs to be
+ * checked to see if it needs fetching.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+
+ /*
+ * For all the tags in the remote_refs string list,
+ * add them to the list of refs to be fetched
+ */
+ for_each_string_list_item(item, &remote_refs) {
+ /* Unless we have already decided to ignore this item... */
+ if (item->util)
+ {
+ struct ref *rm = alloc_ref(item->string);
+ rm->peer_ref = alloc_ref(item->string);
+ hashcpy(rm->old_sha1, item->util);
+ **tail = rm;
+ *tail = &rm->next;
+ }
+ }
+
+ string_list_clear(&remote_refs, 0);
+}
static struct ref *get_ref_map(struct transport *transport,
- struct refspec *refs, int ref_count, int tags,
- int *autotags)
+ struct refspec *refspecs, int refspec_count,
+ int tags, int *autotags)
{
int i;
struct ref *rm;
struct ref *ref_map = NULL;
struct ref **tail = &ref_map;
- const struct ref *remote_refs = transport_get_remote_refs(transport);
+ /* opportunistically-updated references: */
+ struct ref *orefs = NULL, **oref_tail = &orefs;
- if (ref_count || tags == TAGS_SET) {
- struct ref **old_tail;
+ const struct ref *remote_refs = transport_get_remote_refs(transport);
- for (i = 0; i < ref_count; i++) {
- get_fetch_map(remote_refs, &refs[i], &tail, 0);
- if (refs[i].dst && refs[i].dst[0])
+ if (refspec_count) {
+ for (i = 0; i < refspec_count; i++) {
+ get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
+ if (refspecs[i].dst && refspecs[i].dst[0])
*autotags = 1;
}
- /* Merge everything on the command line, but not --tags */
+ /* Merge everything on the command line (but not --tags) */
for (rm = ref_map; rm; rm = rm->next)
rm->fetch_head_status = FETCH_HEAD_MERGE;
- if (tags == TAGS_SET)
- get_fetch_map(remote_refs, tag_refspec, &tail, 0);
/*
- * For any refs that we happen to be fetching via command-line
- * arguments, take the opportunity to update their configured
- * counterparts. However, we do not want to mention these
- * entries in FETCH_HEAD at all, as they would simply be
- * duplicates of existing entries.
+ * For any refs that we happen to be fetching via
+ * command-line arguments, the destination ref might
+ * have been missing or have been different than the
+ * remote-tracking ref that would be derived from the
+ * configured refspec. In these cases, we want to
+ * take the opportunity to update their configured
+ * remote-tracking reference. However, we do not want
+ * to mention these entries in FETCH_HEAD at all, as
+ * they would simply be duplicates of existing
+ * entries, so we set them FETCH_HEAD_IGNORE below.
+ *
+ * We compute these entries now, based only on the
+ * refspecs specified on the command line. But we add
+ * them to the list following the refspecs resulting
+ * from the tags option so that one of the latter,
+ * which has FETCH_HEAD_NOT_FOR_MERGE, is not removed
+ * by ref_remove_duplicates() in favor of one of these
+ * opportunistic entries with FETCH_HEAD_IGNORE.
*/
- old_tail = tail;
for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
get_fetch_map(ref_map, &transport->remote->fetch[i],
- &tail, 1);
- for (rm = *old_tail; rm; rm = rm->next)
- rm->fetch_head_status = FETCH_HEAD_IGNORE;
+ &oref_tail, 1);
+
+ if (tags == TAGS_SET)
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
} else {
/* Use the defaults */
struct remote *remote = transport->remote;
@@ -238,11 +346,21 @@ static struct ref *get_ref_map(struct transport *transport,
tail = &ref_map->next;
}
}
- if (tags == TAGS_DEFAULT && *autotags)
+
+ if (tags == TAGS_SET)
+ /* also fetch all tags */
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+ else if (tags == TAGS_DEFAULT && *autotags)
find_non_local_tags(transport, &ref_map, &tail);
- ref_remove_duplicates(ref_map);
- return ref_map;
+ /* Now append any refs to be updated opportunistically: */
+ *tail = orefs;
+ for (rm = orefs; rm; rm = rm->next) {
+ rm->fetch_head_status = FETCH_HEAD_IGNORE;
+ tail = &rm->next;
+ }
+
+ return ref_remove_duplicates(ref_map);
}
#define STORE_REF_ERROR_OTHER 1
@@ -612,106 +730,6 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
return result;
}
-static int add_existing(const char *refname, const unsigned char *sha1,
- int flag, void *cbdata)
-{
- struct string_list *list = (struct string_list *)cbdata;
- struct string_list_item *item = string_list_insert(list, refname);
- item->util = xmalloc(20);
- hashcpy(item->util, sha1);
- return 0;
-}
-
-static int will_fetch(struct ref **head, const unsigned char *sha1)
-{
- struct ref *rm = *head;
- while (rm) {
- if (!hashcmp(rm->old_sha1, sha1))
- return 1;
- rm = rm->next;
- }
- return 0;
-}
-
-static void find_non_local_tags(struct transport *transport,
- struct ref **head,
- struct ref ***tail)
-{
- struct string_list existing_refs = STRING_LIST_INIT_DUP;
- struct string_list remote_refs = STRING_LIST_INIT_NODUP;
- const struct ref *ref;
- struct string_list_item *item = NULL;
-
- for_each_ref(add_existing, &existing_refs);
- for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
- if (prefixcmp(ref->name, "refs/tags/"))
- continue;
-
- /*
- * The peeled ref always follows the matching base
- * ref, so if we see a peeled ref that we don't want
- * to fetch then we can mark the ref entry in the list
- * as one to ignore by setting util to NULL.
- */
- if (!suffixcmp(ref->name, "^{}")) {
- if (item && !has_sha1_file(ref->old_sha1) &&
- !will_fetch(head, ref->old_sha1) &&
- !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
- item = NULL;
- continue;
- }
-
- /*
- * If item is non-NULL here, then we previously saw a
- * ref not followed by a peeled reference, so we need
- * to check if it is a lightweight tag that we want to
- * fetch.
- */
- if (item && !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
-
- item = NULL;
-
- /* skip duplicates and refs that we already have */
- if (string_list_has_string(&remote_refs, ref->name) ||
- string_list_has_string(&existing_refs, ref->name))
- continue;
-
- item = string_list_insert(&remote_refs, ref->name);
- item->util = (void *)ref->old_sha1;
- }
- string_list_clear(&existing_refs, 1);
-
- /*
- * We may have a final lightweight tag that needs to be
- * checked to see if it needs fetching.
- */
- if (item && !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
-
- /*
- * For all the tags in the remote_refs string list,
- * add them to the list of refs to be fetched
- */
- for_each_string_list_item(item, &remote_refs) {
- /* Unless we have already decided to ignore this item... */
- if (item->util)
- {
- struct ref *rm = alloc_ref(item->string);
- rm->peer_ref = alloc_ref(item->string);
- hashcpy(rm->old_sha1, item->util);
- **tail = rm;
- *tail = &rm->next;
- }
- }
-
- string_list_clear(&remote_refs, 0);
-}
-
static void check_not_current_branch(struct ref *ref_map)
{
struct branch *current_branch = branch_get(NULL);
@@ -831,30 +849,16 @@ static int do_fetch(struct transport *transport,
}
if (prune) {
/*
- * If --tags was specified, pretend that the user gave us
- * the canonical tags refspec
+ * We only prune based on refspecs specified
+ * explicitly (via command line or configuration); we
+ * don't care whether --tags was specified.
*/
- if (tags == TAGS_SET) {
- const char *tags_str = "refs/tags/*:refs/tags/*";
- struct refspec *tags_refspec, *refspec;
-
- /* Copy the refspec and add the tags to it */
- refspec = xcalloc(ref_count + 1, sizeof(struct refspec));
- tags_refspec = parse_fetch_refspec(1, &tags_str);
- memcpy(refspec, refs, ref_count * sizeof(struct refspec));
- memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec));
- ref_count++;
-
- prune_refs(refspec, ref_count, ref_map);
-
- ref_count--;
- /* The rest of the strings belong to fetch_one */
- free_refspec(1, tags_refspec);
- free(refspec);
- } else if (ref_count) {
+ if (ref_count) {
prune_refs(refs, ref_count, ref_map);
} else {
- prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map);
+ prune_refs(transport->remote->fetch,
+ transport->remote->fetch_refspec_nr,
+ ref_map);
}
}
free_refs(ref_map);
@@ -930,8 +934,8 @@ static void add_options_to_argv(struct argv_array *argv)
{
if (dry_run)
argv_array_push(argv, "--dry-run");
- if (prune > 0)
- argv_array_push(argv, "--prune");
+ if (prune != -1)
+ argv_array_push(argv, prune ? "--prune" : "--no-prune");
if (update_head_ok)
argv_array_push(argv, "--update-head-ok");
if (force)
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
new file mode 100644
index 000000000..aa7259608
--- /dev/null
+++ b/builtin/get-tar-commit-id.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005, 2006 Rene Scharfe
+ */
+#include "cache.h"
+#include "commit.h"
+#include "tar.h"
+#include "builtin.h"
+#include "quote.h"
+
+static const char builtin_get_tar_commit_id_usage[] =
+"git get-tar-commit-id < <tarfile>";
+
+/* ustar header + extended global header content */
+#define RECORDSIZE (512)
+#define HEADERSIZE (2 * RECORDSIZE)
+
+int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
+{
+ char buffer[HEADERSIZE];
+ struct ustar_header *header = (struct ustar_header *)buffer;
+ char *content = buffer + RECORDSIZE;
+ ssize_t n;
+
+ if (argc != 1)
+ usage(builtin_get_tar_commit_id_usage);
+
+ n = read_in_full(0, buffer, HEADERSIZE);
+ if (n < HEADERSIZE)
+ die("git get-tar-commit-id: read error");
+ if (header->typeflag[0] != 'g')
+ return 1;
+ if (memcmp(content, "52 comment=", 11))
+ return 1;
+
+ n = write_in_full(1, content + 11, 41);
+ if (n < 41)
+ die_errno("git get-tar-commit-id: write error");
+
+ return 0;
+}
diff --git a/builtin/remote.c b/builtin/remote.c
index 5e4ab66c2..119e9151a 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -6,6 +6,7 @@
#include "strbuf.h"
#include "run-command.h"
#include "refs.h"
+#include "argv-array.h"
static const char * const builtin_remote_usage[] = {
N_("git remote [-v | --verbose]"),
@@ -77,9 +78,6 @@ static const char * const builtin_remote_seturl_usage[] = {
static int verbose;
-static int show_all(void);
-static int prune_remote(const char *remote, int dry_run);
-
static inline int postfixcmp(const char *string, const char *postfix)
{
int len1 = strlen(string), len2 = strlen(postfix);
@@ -1089,6 +1087,64 @@ static int show_push_info_item(struct string_list_item *item, void *cb_data)
return 0;
}
+static int get_one_entry(struct remote *remote, void *priv)
+{
+ struct string_list *list = priv;
+ struct strbuf url_buf = STRBUF_INIT;
+ const char **url;
+ int i, url_nr;
+
+ if (remote->url_nr > 0) {
+ strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
+ string_list_append(list, remote->name)->util =
+ strbuf_detach(&url_buf, NULL);
+ } else
+ string_list_append(list, remote->name)->util = NULL;
+ if (remote->pushurl_nr) {
+ url = remote->pushurl;
+ url_nr = remote->pushurl_nr;
+ } else {
+ url = remote->url;
+ url_nr = remote->url_nr;
+ }
+ for (i = 0; i < url_nr; i++)
+ {
+ strbuf_addf(&url_buf, "%s (push)", url[i]);
+ string_list_append(list, remote->name)->util =
+ strbuf_detach(&url_buf, NULL);
+ }
+
+ return 0;
+}
+
+static int show_all(void)
+{
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ int result;
+
+ list.strdup_strings = 1;
+ result = for_each_remote(get_one_entry, &list);
+
+ if (!result) {
+ int i;
+
+ sort_string_list(&list);
+ for (i = 0; i < list.nr; i++) {
+ struct string_list_item *item = list.items + i;
+ if (verbose)
+ printf("%s\t%s\n", item->string,
+ item->util ? (const char *)item->util : "");
+ else {
+ if (i && !strcmp((item - 1)->string, item->string))
+ continue;
+ printf("%s\n", item->string);
+ }
+ }
+ }
+ string_list_clear(&list, 1);
+ return result;
+}
+
static int show(int argc, const char **argv)
{
int no_query = 0, result = 0, query_flag = 0;
@@ -1251,26 +1307,6 @@ static int set_head(int argc, const char **argv)
return result;
}
-static int prune(int argc, const char **argv)
-{
- int dry_run = 0, result = 0;
- struct option options[] = {
- OPT__DRY_RUN(&dry_run, N_("dry run")),
- OPT_END()
- };
-
- argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
- 0);
-
- if (argc < 1)
- usage_with_options(builtin_remote_prune_usage, options);
-
- for (; argc; argc--, argv++)
- result |= prune_remote(*argv, dry_run);
-
- return result;
-}
-
static int prune_remote(const char *remote, int dry_run)
{
int result = 0, i;
@@ -1309,6 +1345,26 @@ static int prune_remote(const char *remote, int dry_run)
return result;
}
+static int prune(int argc, const char **argv)
+{
+ int dry_run = 0, result = 0;
+ struct option options[] = {
+ OPT__DRY_RUN(&dry_run, N_("dry run")),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
+ 0);
+
+ if (argc < 1)
+ usage_with_options(builtin_remote_prune_usage, options);
+
+ for (; argc; argc--, argv++)
+ result |= prune_remote(*argv, dry_run);
+
+ return result;
+}
+
static int get_remote_default(const char *key, const char *value, void *priv)
{
if (strcmp(key, "remotes.default") == 0) {
@@ -1320,42 +1376,42 @@ static int get_remote_default(const char *key, const char *value, void *priv)
static int update(int argc, const char **argv)
{
- int i, prune = 0;
+ int i, prune = -1;
struct option options[] = {
OPT_BOOL('p', "prune", &prune,
N_("prune remotes after fetching")),
OPT_END()
};
- const char **fetch_argv;
- int fetch_argc = 0;
+ struct argv_array fetch_argv = ARGV_ARRAY_INIT;
int default_defined = 0;
-
- fetch_argv = xmalloc(sizeof(char *) * (argc+5));
+ int retval;
argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
PARSE_OPT_KEEP_ARGV0);
- fetch_argv[fetch_argc++] = "fetch";
+ argv_array_push(&fetch_argv, "fetch");
- if (prune)
- fetch_argv[fetch_argc++] = "--prune";
+ if (prune != -1)
+ argv_array_push(&fetch_argv, prune ? "--prune" : "--no-prune");
if (verbose)
- fetch_argv[fetch_argc++] = "-v";
- fetch_argv[fetch_argc++] = "--multiple";
+ argv_array_push(&fetch_argv, "-v");
+ argv_array_push(&fetch_argv, "--multiple");
if (argc < 2)
- fetch_argv[fetch_argc++] = "default";
+ argv_array_push(&fetch_argv, "default");
for (i = 1; i < argc; i++)
- fetch_argv[fetch_argc++] = argv[i];
+ argv_array_push(&fetch_argv, argv[i]);
- if (strcmp(fetch_argv[fetch_argc-1], "default") == 0) {
+ if (strcmp(fetch_argv.argv[fetch_argv.argc-1], "default") == 0) {
git_config(get_remote_default, &default_defined);
- if (!default_defined)
- fetch_argv[fetch_argc-1] = "--all";
+ if (!default_defined) {
+ argv_array_pop(&fetch_argv);
+ argv_array_push(&fetch_argv, "--all");
+ }
}
- fetch_argv[fetch_argc] = NULL;
-
- return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
+ retval = run_command_v_opt(fetch_argv.argv, RUN_GIT_CMD);
+ argv_array_clear(&fetch_argv);
+ return retval;
}
static int remove_all_fetch_refspecs(const char *remote, const char *key)
@@ -1510,64 +1566,6 @@ static int set_url(int argc, const char **argv)
return 0;
}
-static int get_one_entry(struct remote *remote, void *priv)
-{
- struct string_list *list = priv;
- struct strbuf url_buf = STRBUF_INIT;
- const char **url;
- int i, url_nr;
-
- if (remote->url_nr > 0) {
- strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
- string_list_append(list, remote->name)->util =
- strbuf_detach(&url_buf, NULL);
- } else
- string_list_append(list, remote->name)->util = NULL;
- if (remote->pushurl_nr) {
- url = remote->pushurl;
- url_nr = remote->pushurl_nr;
- } else {
- url = remote->url;
- url_nr = remote->url_nr;
- }
- for (i = 0; i < url_nr; i++)
- {
- strbuf_addf(&url_buf, "%s (push)", url[i]);
- string_list_append(list, remote->name)->util =
- strbuf_detach(&url_buf, NULL);
- }
-
- return 0;
-}
-
-static int show_all(void)
-{
- struct string_list list = STRING_LIST_INIT_NODUP;
- int result;
-
- list.strdup_strings = 1;
- result = for_each_remote(get_one_entry, &list);
-
- if (!result) {
- int i;
-
- sort_string_list(&list);
- for (i = 0; i < list.nr; i++) {
- struct string_list_item *item = list.items + i;
- if (verbose)
- printf("%s\t%s\n", item->string,
- item->util ? (const char *)item->util : "");
- else {
- if (i && !strcmp((item - 1)->string, item->string))
- continue;
- printf("%s\n", item->string);
- }
- }
- }
- string_list_clear(&list, 1);
- return result;
-}
-
int cmd_remote(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
diff --git a/builtin/tar-tree.c b/builtin/tar-tree.c
deleted file mode 100644
index ba3ffe69a..000000000
--- a/builtin/tar-tree.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2005, 2006 Rene Scharfe
- */
-#include "cache.h"
-#include "commit.h"
-#include "tar.h"
-#include "builtin.h"
-#include "quote.h"
-
-static const char tar_tree_usage[] =
-"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
-"*** Note that this command is now deprecated; use \"git archive\" instead.";
-
-static const char builtin_get_tar_commit_id_usage[] =
-"git get-tar-commit-id < <tarfile>";
-
-int cmd_tar_tree(int argc, const char **argv, const char *prefix)
-{
- /*
- * "git tar-tree" is now a wrapper around "git archive --format=tar"
- *
- * $0 --remote=<repo> arg... ==>
- * git archive --format=tar --remote=<repo> arg...
- * $0 tree-ish ==>
- * git archive --format=tar tree-ish
- * $0 tree-ish basedir ==>
- * git archive --format-tar --prefix=basedir tree-ish
- */
- const char **nargv = xcalloc(sizeof(*nargv), argc + 3);
- struct strbuf sb = STRBUF_INIT;
- char *basedir_arg;
- int nargc = 0;
-
- nargv[nargc++] = "archive";
- nargv[nargc++] = "--format=tar";
-
- if (2 <= argc && !prefixcmp(argv[1], "--remote=")) {
- nargv[nargc++] = argv[1];
- argv++;
- argc--;
- }
-
- /*
- * Because it's just a compatibility wrapper, tar-tree supports only
- * the old behaviour of reading attributes from the work tree.
- */
- nargv[nargc++] = "--worktree-attributes";
-
- switch (argc) {
- default:
- usage(tar_tree_usage);
- break;
- case 3:
- /* base-path */
- basedir_arg = xmalloc(strlen(argv[2]) + 11);
- sprintf(basedir_arg, "--prefix=%s/", argv[2]);
- nargv[nargc++] = basedir_arg;
- /* fallthru */
- case 2:
- /* tree-ish */
- nargv[nargc++] = argv[1];
- }
- nargv[nargc] = NULL;
-
- fprintf(stderr,
- "*** \"git tar-tree\" is now deprecated.\n"
- "*** Running \"git archive\" instead.\n***");
- sq_quote_argv(&sb, nargv, 0);
- strbuf_addch(&sb, '\n');
- fputs(sb.buf, stderr);
- strbuf_release(&sb);
- return cmd_archive(nargc, nargv, prefix);
-}
-
-/* ustar header + extended global header content */
-#define RECORDSIZE (512)
-#define HEADERSIZE (2 * RECORDSIZE)
-
-int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
-{
- char buffer[HEADERSIZE];
- struct ustar_header *header = (struct ustar_header *)buffer;
- char *content = buffer + RECORDSIZE;
- ssize_t n;
-
- if (argc != 1)
- usage(builtin_get_tar_commit_id_usage);
-
- n = read_in_full(0, buffer, HEADERSIZE);
- if (n < HEADERSIZE)
- die("git get-tar-commit-id: read error");
- if (header->typeflag[0] != 'g')
- return 1;
- if (memcmp(content, "52 comment=", 11))
- return 1;
-
- n = write_in_full(1, content + 11, 41);
- if (n < 41)
- die_errno("git get-tar-commit-id: write error");
-
- return 0;
-}
diff --git a/command-list.txt b/command-list.txt
index 08b04e2c6..cf36c3d71 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -64,7 +64,6 @@ git-init mainporcelain common
git-instaweb ancillaryinterrogators
gitk mainporcelain
git-log mainporcelain common
-git-lost-found ancillarymanipulators deprecated
git-ls-files plumbinginterrogators
git-ls-remote plumbinginterrogators
git-ls-tree plumbinginterrogators
@@ -88,7 +87,6 @@ git-pack-redundant plumbinginterrogators
git-pack-refs ancillarymanipulators
git-parse-remote synchelpers
git-patch-id purehelpers
-git-peek-remote purehelpers deprecated
git-prune ancillarymanipulators
git-prune-packed plumbingmanipulators
git-pull mainporcelain common
@@ -102,7 +100,6 @@ git-relink ancillarymanipulators
git-remote ancillarymanipulators
git-repack ancillarymanipulators
git-replace ancillarymanipulators
-git-repo-config ancillarymanipulators deprecated
git-request-pull foreignscminterface
git-rerere ancillaryinterrogators
git-reset mainporcelain common
@@ -127,7 +124,6 @@ git-submodule mainporcelain
git-svn foreignscminterface
git-symbolic-ref plumbingmanipulators
git-tag mainporcelain common
-git-tar-tree plumbinginterrogators deprecated
git-unpack-file plumbinginterrogators
git-unpack-objects plumbingmanipulators
git-update-index plumbingmanipulators
diff --git a/commit-slab.h b/commit-slab.h
index d4c828647..cc114b53b 100644
--- a/commit-slab.h
+++ b/commit-slab.h
@@ -22,8 +22,17 @@
*
* Initializes the indegree slab that associates an array of integers
* to each commit. 'stride' specifies how big each array is. The slab
- * that id initialied by the variant without "_with_stride" associates
+ * that is initialized by the variant without "_with_stride" associates
* each commit with an array of one integer.
+ *
+ * - void clear_indegree(struct indegree *);
+ *
+ * Empties the slab. The slab can be reused with the same stride
+ * without calling init_indegree() again or can be reconfigured to a
+ * different stride by calling init_indegree_with_stride().
+ *
+ * Call this function before the slab falls out of scope to avoid
+ * leaking memory.
*/
/* allocate ~512kB at once, allowing for malloc overhead */
@@ -31,6 +40,8 @@
#define COMMIT_SLAB_SIZE (512*1024-32)
#endif
+#define MAYBE_UNUSED __attribute__((__unused__))
+
#define define_commit_slab(slabname, elemtype) \
\
struct slabname { \
@@ -41,8 +52,8 @@ struct slabname { \
}; \
static int stat_ ##slabname## realloc; \
\
-static void init_ ##slabname## _with_stride(struct slabname *s, \
- unsigned stride) \
+static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \
+ unsigned stride) \
{ \
unsigned int elem_size; \
if (!stride) \
@@ -54,12 +65,12 @@ static void init_ ##slabname## _with_stride(struct slabname *s, \
s->slab = NULL; \
} \
\
-static void init_ ##slabname(struct slabname *s) \
+static MAYBE_UNUSED void init_ ##slabname(struct slabname *s) \
{ \
init_ ##slabname## _with_stride(s, 1); \
} \
\
-static void clear_ ##slabname(struct slabname *s) \
+static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
{ \
int i; \
for (i = 0; i < s->slab_count; i++) \
@@ -69,8 +80,8 @@ static void clear_ ##slabname(struct slabname *s) \
s->slab = NULL; \
} \
\
-static elemtype *slabname## _at(struct slabname *s, \
- const struct commit *c) \
+static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
+ const struct commit *c) \
{ \
int nth_slab, nth_slot; \
\
@@ -80,7 +91,7 @@ static elemtype *slabname## _at(struct slabname *s, \
if (s->slab_count <= nth_slab) { \
int i; \
s->slab = xrealloc(s->slab, \
- (nth_slab + 1) * sizeof(s->slab)); \
+ (nth_slab + 1) * sizeof(*s->slab)); \
stat_ ##slabname## realloc++; \
for (i = s->slab_count; i <= nth_slab; i++) \
s->slab[i] = NULL; \
@@ -94,4 +105,16 @@ static elemtype *slabname## _at(struct slabname *s, \
\
static int stat_ ##slabname## realloc
+/*
+ * Note that this seemingly redundant second declaration is required
+ * to allow a terminating semicolon, which makes instantiations look
+ * like function declarations. I.e., the expansion of
+ *
+ * define_commit_slab(indegree, int);
+ *
+ * ends in 'static int stat_indegreerealloc;'. This would otherwise
+ * be a syntax error according (at least) to ISO C. It's hard to
+ * catch because GCC silently parses it by default.
+ */
+
#endif /* COMMIT_SLAB_H */
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index 4374771df..4374771df 100644..100755
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
diff --git a/compat/vcbuild/scripts/lib.pl b/compat/vcbuild/scripts/lib.pl
index d8054e469..d8054e469 100644..100755
--- a/compat/vcbuild/scripts/lib.pl
+++ b/compat/vcbuild/scripts/lib.pl
diff --git a/config.c b/config.c
index e1d66a145..a2c22ab43 100644
--- a/config.c
+++ b/config.c
@@ -1210,15 +1210,14 @@ int git_config(config_fn_t fn, void *data)
* Find all the stuff for git_config_set() below.
*/
-#define MAX_MATCHES 512
-
static struct {
int baselen;
char *key;
int do_not_match;
regex_t *value_regex;
int multi_replace;
- size_t offset[MAX_MATCHES];
+ size_t *offset;
+ unsigned int offset_alloc;
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
int seen;
} store;
@@ -1241,11 +1240,11 @@ static int store_aux(const char *key, const char *value, void *cb)
if (matches(key, value)) {
if (store.seen == 1 && store.multi_replace == 0) {
warning("%s has multiple values", key);
- } else if (store.seen >= MAX_MATCHES) {
- error("too many matches for %s", key);
- return 1;
}
+ ALLOC_GROW(store.offset, store.seen + 1,
+ store.offset_alloc);
+
store.offset[store.seen] = cf->do_ftell(cf);
store.seen++;
}
@@ -1273,11 +1272,15 @@ static int store_aux(const char *key, const char *value, void *cb)
* Do not increment matches: this is no match, but we
* just made sure we are in the desired section.
*/
+ ALLOC_GROW(store.offset, store.seen + 1,
+ store.offset_alloc);
store.offset[store.seen] = cf->do_ftell(cf);
/* fallthru */
case SECTION_END_SEEN:
case START:
if (matches(key, value)) {
+ ALLOC_GROW(store.offset, store.seen + 1,
+ store.offset_alloc);
store.offset[store.seen] = cf->do_ftell(cf);
store.state = KEY_SEEN;
store.seen++;
@@ -1285,6 +1288,9 @@ static int store_aux(const char *key, const char *value, void *cb)
if (strrchr(key, '.') - key == store.baselen &&
!strncmp(key, store.key, store.baselen)) {
store.state = SECTION_SEEN;
+ ALLOC_GROW(store.offset,
+ store.seen + 1,
+ store.offset_alloc);
store.offset[store.seen] = cf->do_ftell(cf);
}
}
@@ -1583,6 +1589,7 @@ int git_config_set_multivar_in_file(const char *config_filename,
}
}
+ ALLOC_GROW(store.offset, 1, store.offset_alloc);
store.offset[0] = 0;
store.state = START;
store.seen = 0;
diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 23da787dc..23da787dc 100644..100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
diff --git a/contrib/buildsystems/generate b/contrib/buildsystems/generate
index bc10f25ff..bc10f25ff 100644..100755
--- a/contrib/buildsystems/generate
+++ b/contrib/buildsystems/generate
diff --git a/contrib/buildsystems/parse.pl b/contrib/buildsystems/parse.pl
index c9656ece9..c9656ece9 100644..100755
--- a/contrib/buildsystems/parse.pl
+++ b/contrib/buildsystems/parse.pl
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index dba3c1570..51c2dd4de 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1,5 +1,3 @@
-#!bash
-#
# bash/zsh completion support for core Git.
#
# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
@@ -673,7 +671,6 @@ __git_list_porcelain_commands ()
index-pack) : plumbing;;
init-db) : deprecated;;
local-fetch) : plumbing;;
- lost-found) : infrequent;;
ls-files) : plumbing;;
ls-remote) : plumbing;;
ls-tree) : plumbing;;
@@ -687,14 +684,12 @@ __git_list_porcelain_commands ()
pack-refs) : plumbing;;
parse-remote) : plumbing;;
patch-id) : plumbing;;
- peek-remote) : plumbing;;
prune) : plumbing;;
prune-packed) : plumbing;;
quiltimport) : import;;
read-tree) : plumbing;;
receive-pack) : plumbing;;
remote-*) : transport;;
- repo-config) : deprecated;;
rerere) : plumbing;;
rev-list) : plumbing;;
rev-parse) : plumbing;;
@@ -707,7 +702,6 @@ __git_list_porcelain_commands ()
ssh-*) : transport;;
stripspace) : plumbing;;
symbolic-ref) : plumbing;;
- tar-tree) : deprecated;;
unpack-file) : plumbing;;
unpack-objects) : plumbing;;
update-index) : plumbing;;
diff --git a/contrib/completion/git-completion.tcsh b/contrib/completion/git-completion.tcsh
index eaacaf0c3..6104a42a2 100644
--- a/contrib/completion/git-completion.tcsh
+++ b/contrib/completion/git-completion.tcsh
@@ -1,5 +1,3 @@
-#!tcsh
-#
# tcsh completion support for core Git.
#
# Copyright (C) 2012 Marc Khouzam <marc.khouzam@gmail.com>
diff --git a/contrib/examples/git-whatchanged.sh b/contrib/examples/git-whatchanged.sh
index 1fb9feb34..2edbdc6d9 100755
--- a/contrib/examples/git-whatchanged.sh
+++ b/contrib/examples/git-whatchanged.sh
@@ -9,12 +9,12 @@ case "$0" in
*whatchanged)
count=
test -z "$diff_tree_flags" &&
- diff_tree_flags=$(git-repo-config --get whatchanged.difftree)
+ diff_tree_flags=$(git config --get whatchanged.difftree)
diff_tree_default_flags='-c -M --abbrev' ;;
*show)
count=-n1
test -z "$diff_tree_flags" &&
- diff_tree_flags=$(git-repo-config --get show.difftree)
+ diff_tree_flags=$(git config --get show.difftree)
diff_tree_default_flags='--cc --always' ;;
esac
test -z "$diff_tree_flags" &&
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 8ee410f84..8747b8433 100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -22,7 +22,6 @@
# For example, on debian the hook is stored in
# /usr/share/git-core/contrib/hooks/post-receive-email:
#
-# chmod a+x post-receive-email
# cd /path/to/your/repository.git
# ln -sf /usr/share/git-core/contrib/hooks/post-receive-email hooks/post-receive
#
diff --git a/contrib/hooks/pre-auto-gc-battery b/contrib/hooks/pre-auto-gc-battery
index 1f914c94a..9d0c2d199 100644..100755
--- a/contrib/hooks/pre-auto-gc-battery
+++ b/contrib/hooks/pre-auto-gc-battery
@@ -13,7 +13,6 @@
# For example, if the hook is stored in
# /usr/share/git-core/contrib/hooks/pre-auto-gc-battery:
#
-# chmod a+x pre-auto-gc-battery
# cd /path/to/your/repository.git
# ln -sf /usr/share/git-core/contrib/hooks/pre-auto-gc-battery \
# hooks/pre-auto-gc
diff --git a/contrib/hooks/setgitperms.perl b/contrib/hooks/setgitperms.perl
index 2770a1b1d..2770a1b1d 100644..100755
--- a/contrib/hooks/setgitperms.perl
+++ b/contrib/hooks/setgitperms.perl
diff --git a/contrib/hooks/update-paranoid b/contrib/hooks/update-paranoid
index d18b317b2..d18b317b2 100644..100755
--- a/contrib/hooks/update-paranoid
+++ b/contrib/hooks/update-paranoid
diff --git a/contrib/p4import/README b/contrib/p4import/README
deleted file mode 100644
index b9892b679..000000000
--- a/contrib/p4import/README
+++ /dev/null
@@ -1 +0,0 @@
-Please see contrib/fast-import/git-p4 for a better Perforce importer.
diff --git a/contrib/p4import/git-p4import.py b/contrib/p4import/git-p4import.py
deleted file mode 100644
index 593d6a068..000000000
--- a/contrib/p4import/git-p4import.py
+++ /dev/null
@@ -1,365 +0,0 @@
-#!/usr/bin/env python
-#
-# This tool is copyright (c) 2006, Sean Estabrooks.
-# It is released under the Gnu Public License, version 2.
-#
-# Import Perforce branches into Git repositories.
-# Checking out the files is done by calling the standard p4
-# client which you must have properly configured yourself
-#
-
-import marshal
-import os
-import sys
-import time
-import getopt
-
-if sys.hexversion < 0x02020000:
- # The behavior of the marshal module changed significantly in 2.2
- sys.stderr.write("git-p4import.py: requires Python 2.2 or later.\n")
- sys.exit(1)
-
-from signal import signal, \
- SIGPIPE, SIGINT, SIG_DFL, \
- default_int_handler
-
-signal(SIGPIPE, SIG_DFL)
-s = signal(SIGINT, SIG_DFL)
-if s != default_int_handler:
- signal(SIGINT, s)
-
-def die(msg, *args):
- for a in args:
- msg = "%s %s" % (msg, a)
- print "git-p4import fatal error:", msg
- sys.exit(1)
-
-def usage():
- print "USAGE: git-p4import [-q|-v] [--authors=<file>] [-t <timezone>] [//p4repo/path <branch>]"
- sys.exit(1)
-
-verbosity = 1
-logfile = "/dev/null"
-ignore_warnings = False
-stitch = 0
-tagall = True
-
-def report(level, msg, *args):
- global verbosity
- global logfile
- for a in args:
- msg = "%s %s" % (msg, a)
- fd = open(logfile, "a")
- fd.writelines(msg)
- fd.close()
- if level <= verbosity:
- print msg
-
-class p4_command:
- def __init__(self, _repopath):
- try:
- global logfile
- self.userlist = {}
- if _repopath[-1] == '/':
- self.repopath = _repopath[:-1]
- else:
- self.repopath = _repopath
- if self.repopath[-4:] != "/...":
- self.repopath= "%s/..." % self.repopath
- f=os.popen('p4 -V 2>>%s'%logfile, 'rb')
- a = f.readlines()
- if f.close():
- raise
- except:
- die("Could not find the \"p4\" command")
-
- def p4(self, cmd, *args):
- global logfile
- cmd = "%s %s" % (cmd, ' '.join(args))
- report(2, "P4:", cmd)
- f=os.popen('p4 -G %s 2>>%s' % (cmd,logfile), 'rb')
- list = []
- while 1:
- try:
- list.append(marshal.load(f))
- except EOFError:
- break
- self.ret = f.close()
- return list
-
- def sync(self, id, force=False, trick=False, test=False):
- if force:
- ret = self.p4("sync -f %s@%s"%(self.repopath, id))[0]
- elif trick:
- ret = self.p4("sync -k %s@%s"%(self.repopath, id))[0]
- elif test:
- ret = self.p4("sync -n %s@%s"%(self.repopath, id))[0]
- else:
- ret = self.p4("sync %s@%s"%(self.repopath, id))[0]
- if ret['code'] == "error":
- data = ret['data'].upper()
- if data.find('VIEW') > 0:
- die("Perforce reports %s is not in client view"% self.repopath)
- elif data.find('UP-TO-DATE') < 0:
- die("Could not sync files from perforce", self.repopath)
-
- def changes(self, since=0):
- try:
- list = []
- for rec in self.p4("changes %s@%s,#head" % (self.repopath, since+1)):
- list.append(rec['change'])
- list.reverse()
- return list
- except:
- return []
-
- def authors(self, filename):
- f=open(filename)
- for l in f.readlines():
- self.userlist[l[:l.find('=')].rstrip()] = \
- (l[l.find('=')+1:l.find('<')].rstrip(),l[l.find('<')+1:l.find('>')])
- f.close()
- for f,e in self.userlist.items():
- report(2, f, ":", e[0], " <", e[1], ">")
-
- def _get_user(self, id):
- if not self.userlist.has_key(id):
- try:
- user = self.p4("users", id)[0]
- self.userlist[id] = (user['FullName'], user['Email'])
- except:
- self.userlist[id] = (id, "")
- return self.userlist[id]
-
- def _format_date(self, ticks):
- symbol='+'
- name = time.tzname[0]
- offset = time.timezone
- if ticks[8]:
- name = time.tzname[1]
- offset = time.altzone
- if offset < 0:
- offset *= -1
- symbol = '-'
- localo = "%s%02d%02d %s" % (symbol, offset / 3600, offset % 3600, name)
- tickso = time.strftime("%a %b %d %H:%M:%S %Y", ticks)
- return "%s %s" % (tickso, localo)
-
- def where(self):
- try:
- return self.p4("where %s" % self.repopath)[-1]['path']
- except:
- return ""
-
- def describe(self, num):
- desc = self.p4("describe -s", num)[0]
- self.msg = desc['desc']
- self.author, self.email = self._get_user(desc['user'])
- self.date = self._format_date(time.localtime(long(desc['time'])))
- return self
-
-class git_command:
- def __init__(self):
- try:
- self.version = self.git("--version")[0][12:].rstrip()
- except:
- die("Could not find the \"git\" command")
- try:
- self.gitdir = self.get_single("rev-parse --git-dir")
- report(2, "gdir:", self.gitdir)
- except:
- die("Not a git repository... did you forget to \"git init\" ?")
- try:
- self.cdup = self.get_single("rev-parse --show-cdup")
- if self.cdup != "":
- os.chdir(self.cdup)
- self.topdir = os.getcwd()
- report(2, "topdir:", self.topdir)
- except:
- die("Could not find top git directory")
-
- def git(self, cmd):
- global logfile
- report(2, "GIT:", cmd)
- f=os.popen('git %s 2>>%s' % (cmd,logfile), 'rb')
- r=f.readlines()
- self.ret = f.close()
- return r
-
- def get_single(self, cmd):
- return self.git(cmd)[0].rstrip()
-
- def current_branch(self):
- try:
- testit = self.git("rev-parse --verify HEAD")[0]
- return self.git("symbolic-ref HEAD")[0][11:].rstrip()
- except:
- return None
-
- def get_config(self, variable):
- try:
- return self.git("config --get %s" % variable)[0].rstrip()
- except:
- return None
-
- def set_config(self, variable, value):
- try:
- self.git("config %s %s"%(variable, value) )
- except:
- die("Could not set %s to " % variable, value)
-
- def make_tag(self, name, head):
- self.git("tag -f %s %s"%(name,head))
-
- def top_change(self, branch):
- try:
- a=self.get_single("name-rev --tags refs/heads/%s" % branch)
- loc = a.find(' tags/') + 6
- if a[loc:loc+3] != "p4/":
- raise
- return int(a[loc+3:][:-2])
- except:
- return 0
-
- def update_index(self):
- self.git("ls-files -m -d -o -z | git update-index --add --remove -z --stdin")
-
- def checkout(self, branch):
- self.git("checkout %s" % branch)
-
- def repoint_head(self, branch):
- self.git("symbolic-ref HEAD refs/heads/%s" % branch)
-
- def remove_files(self):
- self.git("ls-files | xargs rm")
-
- def clean_directories(self):
- self.git("clean -d")
-
- def fresh_branch(self, branch):
- report(1, "Creating new branch", branch)
- self.git("ls-files | xargs rm")
- os.remove(".git/index")
- self.repoint_head(branch)
- self.git("clean -d")
-
- def basedir(self):
- return self.topdir
-
- def commit(self, author, email, date, msg, id):
- self.update_index()
- fd=open(".msg", "w")
- fd.writelines(msg)
- fd.close()
- try:
- current = self.get_single("rev-parse --verify HEAD")
- head = "-p HEAD"
- except:
- current = ""
- head = ""
- tree = self.get_single("write-tree")
- for r,l in [('DATE',date),('NAME',author),('EMAIL',email)]:
- os.environ['GIT_AUTHOR_%s'%r] = l
- os.environ['GIT_COMMITTER_%s'%r] = l
- commit = self.get_single("commit-tree %s %s < .msg" % (tree,head))
- os.remove(".msg")
- self.make_tag("p4/%s"%id, commit)
- self.git("update-ref HEAD %s %s" % (commit, current) )
-
-try:
- opts, args = getopt.getopt(sys.argv[1:], "qhvt:",
- ["authors=","help","stitch=","timezone=","log=","ignore","notags"])
-except getopt.GetoptError:
- usage()
-
-for o, a in opts:
- if o == "-q":
- verbosity = 0
- if o == "-v":
- verbosity += 1
- if o in ("--log"):
- logfile = a
- if o in ("--notags"):
- tagall = False
- if o in ("-h", "--help"):
- usage()
- if o in ("--ignore"):
- ignore_warnings = True
-
-git = git_command()
-branch=git.current_branch()
-
-for o, a in opts:
- if o in ("-t", "--timezone"):
- git.set_config("perforce.timezone", a)
- if o in ("--stitch"):
- git.set_config("perforce.%s.path" % branch, a)
- stitch = 1
-
-if len(args) == 2:
- branch = args[1]
- git.checkout(branch)
- if branch == git.current_branch():
- die("Branch %s already exists!" % branch)
- report(1, "Setting perforce to ", args[0])
- git.set_config("perforce.%s.path" % branch, args[0])
-elif len(args) != 0:
- die("You must specify the perforce //depot/path and git branch")
-
-p4path = git.get_config("perforce.%s.path" % branch)
-if p4path == None:
- die("Do not know Perforce //depot/path for git branch", branch)
-
-p4 = p4_command(p4path)
-
-for o, a in opts:
- if o in ("-a", "--authors"):
- p4.authors(a)
-
-localdir = git.basedir()
-if p4.where()[:len(localdir)] != localdir:
- report(1, "**WARNING** Appears p4 client is misconfigured")
- report(1, " for sync from %s to %s" % (p4.repopath, localdir))
- if ignore_warnings != True:
- die("Reconfigure or use \"--ignore\" on command line")
-
-if stitch == 0:
- top = git.top_change(branch)
-else:
- top = 0
-changes = p4.changes(top)
-count = len(changes)
-if count == 0:
- report(1, "Already up to date...")
- sys.exit(0)
-
-ptz = git.get_config("perforce.timezone")
-if ptz:
- report(1, "Setting timezone to", ptz)
- os.environ['TZ'] = ptz
- time.tzset()
-
-if stitch == 1:
- git.remove_files()
- git.clean_directories()
- p4.sync(changes[0], force=True)
-elif top == 0 and branch != git.current_branch():
- p4.sync(changes[0], test=True)
- report(1, "Creating new initial commit");
- git.fresh_branch(branch)
- p4.sync(changes[0], force=True)
-else:
- p4.sync(changes[0], trick=True)
-
-report(1, "processing %s changes from p4 (%s) to git (%s)" % (count, p4.repopath, branch))
-for id in changes:
- report(1, "Importing changeset", id)
- change = p4.describe(id)
- p4.sync(id)
- if tagall :
- git.commit(change.author, change.email, change.date, change.msg, id)
- else:
- git.commit(change.author, change.email, change.date, change.msg, "import")
- if stitch == 1:
- git.clean_directories()
- stitch = 0
diff --git a/contrib/p4import/git-p4import.txt b/contrib/p4import/git-p4import.txt
deleted file mode 100644
index 9967587fe..000000000
--- a/contrib/p4import/git-p4import.txt
+++ /dev/null
@@ -1,167 +0,0 @@
-git-p4import(1)
-===============
-
-NAME
-----
-git-p4import - Import a Perforce repository into git
-
-
-SYNOPSIS
---------
-[verse]
-`git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>]
- <//p4repo/path> <branch>
-`git-p4import` --stitch <//p4repo/path>
-`git-p4import`
-
-
-DESCRIPTION
------------
-Import a Perforce repository into an existing git repository. When
-a <//p4repo/path> and <branch> are specified a new branch with the
-given name will be created and the initial import will begin.
-
-Once the initial import is complete you can do an incremental import
-of new commits from the Perforce repository. You do this by checking
-out the appropriate git branch and then running `git-p4import` without
-any options.
-
-The standard p4 client is used to communicate with the Perforce
-repository; it must be configured correctly in order for `git-p4import`
-to operate (see below).
-
-
-OPTIONS
--------
--q::
- Do not display any progress information.
-
--v::
- Give extra progress information.
-
-\--authors::
- Specify an authors file containing a mapping of Perforce user
- ids to full names and email addresses (see Notes below).
-
-\--notags::
- Do not create a tag for each imported commit.
-
-\--stitch::
- Import the contents of the given perforce branch into the
- currently checked out git branch.
-
-\--log::
- Store debugging information in the specified file.
-
--t::
- Specify that the remote repository is in the specified timezone.
- Timezone must be in the format "US/Pacific" or "Europe/London"
- etc. You only need to specify this once, it will be saved in
- the git config file for the repository.
-
-<//p4repo/path>::
- The Perforce path that will be imported into the specified branch.
-
-<branch>::
- The new branch that will be created to hold the Perforce imports.
-
-
-P4 Client
----------
-You must make the `p4` client command available in your $PATH and
-configure it to communicate with the target Perforce repository.
-Typically this means you must set the "$P4PORT" and "$P4CLIENT"
-environment variables.
-
-You must also configure a `p4` client "view" which maps the Perforce
-branch into the top level of your git repository, for example:
-
-------------
-Client: myhost
-
-Root: /home/sean/import
-
-Options: noallwrite clobber nocompress unlocked modtime rmdir
-
-View:
- //public/jam/... //myhost/jam/...
-------------
-
-With the above `p4` client setup, you could import the "jam"
-perforce branch into a branch named "jammy", like so:
-
-------------
-$ mkdir -p /home/sean/import/jam
-$ cd /home/sean/import/jam
-$ git init
-$ git p4import //public/jam jammy
-------------
-
-
-Multiple Branches
------------------
-Note that by creating multiple "views" you can use `git-p4import`
-to import additional branches into the same git repository.
-However, the `p4` client has a limitation in that it silently
-ignores all but the last "view" that maps into the same local
-directory. So the following will *not* work:
-
-------------
-View:
- //public/jam/... //myhost/jam/...
- //public/other/... //myhost/jam/...
- //public/guest/... //myhost/jam/...
-------------
-
-If you want more than one Perforce branch to be imported into the
-same directory you must employ a workaround. A simple option is
-to adjust your `p4` client before each import to only include a
-single view.
-
-Another option is to create multiple symlinks locally which all
-point to the same directory in your git repository and then use
-one per "view" instead of listing the actual directory.
-
-
-Tags
-----
-A git tag of the form p4/xx is created for every change imported from
-the Perforce repository where xx is the Perforce changeset number.
-Therefore after the import you can use git to access any commit by its
-Perforce number, e.g. git show p4/327.
-
-The tag associated with the HEAD commit is also how `git-p4import`
-determines if there are new changes to incrementally import from the
-Perforce repository.
-
-If you import from a repository with many thousands of changes
-you will have an equal number of p4/xxxx git tags. Git tags can
-be expensive in terms of disk space and repository operations.
-If you don't need to perform further incremental imports, you
-may delete the tags.
-
-
-Notes
------
-You can interrupt the import (e.g. ctrl-c) at any time and restart it
-without worry.
-
-Author information is automatically determined by querying the
-Perforce "users" table using the id associated with each change.
-However, if you want to manually supply these mappings you can do
-so with the "--authors" option. It accepts a file containing a list
-of mappings with each line containing one mapping in the format:
-
-------------
- perforce_id = Full Name <email@address.com>
-------------
-
-
-Author
-------
-Written by Sean Estabrooks <seanlkml@sympatico.ca>
-
-
-GIT
----
-Part of the gitlink:git[7] suite
diff --git a/git-gui/Makefile b/git-gui/Makefile
index e9c2bc347..cde8b2ea3 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -4,7 +4,7 @@ all::
#
# Define NO_MSGFMT if you do not have msgfmt from the GNU gettext
# package and want to use our rough pure Tcl po->msg translator.
-# TCL_PATH must be vaild for this to work.
+# TCL_PATH must be valid for this to work.
#
GIT-VERSION-FILE: FORCE
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 153f85da0..db46ac50b 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -894,6 +894,7 @@ set default_config(gui.textconv) true
set default_config(gui.pruneduringfetch) false
set default_config(gui.trustmtime) false
set default_config(gui.fastcopyblame) false
+set default_config(gui.maxrecentrepo) 10
set default_config(gui.copyblamethreshold) 40
set default_config(gui.blamehistoryctx) 7
set default_config(gui.diffcontext) 5
@@ -912,6 +913,7 @@ set font_descs {
{fontdiff font_diff {mc "Diff/Console Font"}}
}
set default_config(gui.stageuntracked) ask
+set default_config(gui.displayuntracked) true
######################################################################
##
@@ -1282,7 +1284,11 @@ apply_config
# v1.7.0 introduced --show-toplevel to return the canonical work-tree
if {[package vsatisfies $_git_version 1.7.0]} {
- set _gitworktree [git rev-parse --show-toplevel]
+ if { [is_Cygwin] } {
+ catch {set _gitworktree [exec cygpath --windows [git rev-parse --show-toplevel]]}
+ } else {
+ set _gitworktree [git rev-parse --show-toplevel]
+ }
} else {
# try to set work tree from environment, core.worktree or use
# cdup to obtain a relative path to the top of the worktree. If
@@ -1550,18 +1556,23 @@ proc rescan_stage2 {fd after} {
set buf_rdf {}
set buf_rlo {}
- set rescan_active 3
+ set rescan_active 2
ui_status [mc "Scanning for modified files ..."]
set fd_di [git_read diff-index --cached -z [PARENT]]
set fd_df [git_read diff-files -z]
- set fd_lo [eval git_read ls-files --others -z $ls_others]
fconfigure $fd_di -blocking 0 -translation binary -encoding binary
fconfigure $fd_df -blocking 0 -translation binary -encoding binary
- fconfigure $fd_lo -blocking 0 -translation binary -encoding binary
+
fileevent $fd_di readable [list read_diff_index $fd_di $after]
fileevent $fd_df readable [list read_diff_files $fd_df $after]
- fileevent $fd_lo readable [list read_ls_others $fd_lo $after]
+
+ if {[is_config_true gui.displayuntracked]} {
+ set fd_lo [eval git_read ls-files --others -z $ls_others]
+ fconfigure $fd_lo -blocking 0 -translation binary -encoding binary
+ fileevent $fd_lo readable [list read_ls_others $fd_lo $after]
+ incr rescan_active
+ }
}
proc load_message {file {encoding {}}} {
@@ -2654,6 +2665,16 @@ if {![is_bare]} {
.mbar.repository add command \
-label [mc "Explore Working Copy"] \
-command {do_explore}
+}
+
+if {[is_Windows]} {
+ .mbar.repository add command \
+ -label [mc "Git Bash"] \
+ -command {eval exec [auto_execok start] \
+ [list "Git Bash" bash --login -l &]}
+}
+
+if {[is_Windows] || ![is_bare]} {
.mbar.repository add separator
}
@@ -3203,13 +3224,19 @@ unset i
# -- Diff and Commit Area
#
-${NS}::frame .vpane.lower -height 300 -width 400
+${NS}::panedwindow .vpane.lower -orient vertical
${NS}::frame .vpane.lower.commarea
-${NS}::frame .vpane.lower.diff -relief sunken -borderwidth 1
-pack .vpane.lower.diff -fill both -expand 1
-pack .vpane.lower.commarea -side bottom -fill x
+${NS}::frame .vpane.lower.diff -relief sunken -borderwidth 1 -height 500
+.vpane.lower add .vpane.lower.diff
+.vpane.lower add .vpane.lower.commarea
.vpane add .vpane.lower
-if {!$use_ttk} {.vpane paneconfigure .vpane.lower -sticky nsew}
+if {$use_ttk} {
+ .vpane.lower pane .vpane.lower.diff -weight 1
+ .vpane.lower pane .vpane.lower.commarea -weight 0
+} else {
+ .vpane.lower paneconfigure .vpane.lower.diff -stretch always
+ .vpane.lower paneconfigure .vpane.lower.commarea -stretch never
+}
# -- Commit Area Buttons
#
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index 324f7744c..b1d15f462 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -5,7 +5,7 @@ class blame {
image create photo ::blame::img_back_arrow -data {R0lGODlhGAAYAIUAAPwCBEzKXFTSZIz+nGzmhGzqfGTidIT+nEzGXHTqhGzmfGzifFzadETCVES+VARWDFzWbHzyjAReDGTadFTOZDSyRDyyTCymPARaFGTedFzSbDy2TCyqRCyqPARaDAyCHES6VDy6VCyiPAR6HCSeNByWLARyFARiDARqFGTifARiFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAYABgAAAajQIBwSCwaj8ikcsk0BppJwRPqHEypQwHBis0WDAdEFyBIKBaMAKLBdjQeSkFBYTBAIvgEoS6JmhUTEwIUDQ4VFhcMGEhyCgoZExoUaxsWHB0THkgfAXUGAhoBDSAVFR0XBnCbDRmgog0hpSIiDJpJIyEQhBUcJCIlwA22SSYVogknEg8eD82qSigdDSknY0IqJQXPYxIl1dZCGNvWw+Dm510GQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7}
-# Persistant data (survives loads)
+# Persistent data (survives loads)
#
field history {}; # viewer history: {commit path}
field header ; # array commit,key -> header field
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index ee58981f5..3c10bc656 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -24,6 +24,10 @@ field sorted_recent ; # recent repositories (sorted)
constructor pick {} {
global M1T M1B use_ttk NS
+ if {[set maxrecent [get_config gui.maxrecentrepo]] eq {}} {
+ set maxrecent 10
+ }
+
make_dialog top w
wm title $top [mc "Git Gui"]
@@ -148,7 +152,7 @@ constructor pick {} {
-background [get_bg_color $w_body.recentlabel] \
-wrap none \
-width 50 \
- -height 10
+ -height $maxrecent
$w_recentlist tag conf link \
-foreground blue \
-underline 1
@@ -264,7 +268,11 @@ proc _append_recentrepos {path} {
git config --global --add gui.recentrepo $path
load_config 1
- while {[llength $recent] > 10} {
+ if {[set maxrecent [get_config gui.maxrecentrepo]] eq {}} {
+ set maxrecent 10
+ }
+
+ while {[llength $recent] > $maxrecent} {
_unset_recentrepo [lindex $recent 0]
set recent [lrange $recent 1 end]
}
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index 8efbbdde2..74a81a7b4 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -414,7 +414,7 @@ proc revert_helper {txt paths} {
# such distinction is needed in some languages. Previously, the
# code used "Revert changes in" for both, but that can't work
# in languages where 'in' must be combined with word from
- # rest of string (in diffrent way for both cases of course).
+ # rest of string (in different way for both cases of course).
#
# FIXME: Unfortunately, even that isn't enough in some languages
# as they have quite complex plural-form rules. Unfortunately,
diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl
index 0cf1da1d7..23c9ae72a 100644
--- a/git-gui/lib/option.tcl
+++ b/git-gui/lib/option.tcl
@@ -150,6 +150,7 @@ proc do_options {} {
{b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
{b gui.textconv {mc "Use Textconv For Diffs and Blames"}}
{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
+ {i-0..100 gui.maxrecentrepo {mc "Maximum Length of Recent Repositories List"}}
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
{i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}}
{i-1..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
@@ -159,6 +160,7 @@ proc do_options {} {
{c gui.encoding {mc "Default File Contents Encoding"}}
{b gui.warndetachedcommit {mc "Warn before committing to a detached head"}}
{s gui.stageuntracked {mc "Staging of untracked files"} {list "yes" "no" "ask"}}
+ {b gui.displayuntracked {mc "Show untracked files"}}
} {
set type [lindex $option 0]
set name [lindex $option 1]
diff --git a/git-gui/lib/spellcheck.tcl b/git-gui/lib/spellcheck.tcl
index e6120303e..538d61c79 100644
--- a/git-gui/lib/spellcheck.tcl
+++ b/git-gui/lib/spellcheck.tcl
@@ -14,7 +14,7 @@ field w_menu ; # context menu for the widget
field s_menuidx 0 ; # last index of insertion into $w_menu
field s_i {} ; # timer registration for _run callbacks
-field s_clear 0 ; # did we erase mispelled tags yet?
+field s_clear 0 ; # did we erase misspelled tags yet?
field s_seen [list] ; # lines last seen from $w_text in _run
field s_checked [list] ; # lines already checked
field s_pending [list] ; # [$line $data] sent to ispell/aspell
@@ -259,7 +259,7 @@ method _run {} {
if {$n == $cur_line
&& ![regexp {^\W$} [$w_text get $cur_pos insert]]} {
- # If the current word is mispelled remove the tag
+ # If the current word is misspelled remove the tag
# but force a spellcheck later.
#
set tags [$w_text tag names $cur_pos]
diff --git a/git-gui/macosx/Info.plist b/git-gui/macosx/Info.plist
index b3bf15fa1..1ade121c4 100644
--- a/git-gui/macosx/Info.plist
+++ b/git-gui/macosx/Info.plist
@@ -24,5 +24,7 @@
<string>GITg</string>
<key>CFBundleVersion</key>
<string>@@GITGUI_VERSION@@</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
</dict>
</plist>
diff --git a/git-lost-found.sh b/git-lost-found.sh
deleted file mode 100755
index 0b3e8c7a8..000000000
--- a/git-lost-found.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-USAGE=''
-SUBDIRECTORY_OK='Yes'
-OPTIONS_SPEC=
-. git-sh-setup
-
-echo "WARNING: '$0' is deprecated in favor of 'git fsck --lost-found'" >&2
-
-if [ "$#" != "0" ]
-then
- usage
-fi
-
-laf="$GIT_DIR/lost-found"
-rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
-
-git fsck --full --no-reflogs |
-while read dangling type sha1
-do
- case "$dangling" in
- dangling)
- if git rev-parse -q --verify "$sha1^0" >/dev/null
- then
- dir="$laf/commit"
- git show-branch "$sha1"
- else
- dir="$laf/other"
- fi
- echo "$sha1" >"$dir/$sha1"
- ;;
- esac
-done
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index a280f4981..c45a02030 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -1,5 +1,4 @@
-#!/bin/sh
-# git-mergetool--lib is a library for common merge tool functions
+# git-mergetool--lib is a shell library for common merge tool functions
: ${MERGE_TOOLS_DIR=$(git --exec-path)/mergetools}
diff --git a/git-p4.py b/git-p4.py
index 06a3cc612..5ea8bb8fc 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1311,7 +1311,7 @@ class P4Submit(Command, P4UserMap):
else:
die("unknown modifier %s for %s" % (modifier, path))
- diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id)
+ diffcmd = "git diff-tree -p \"%s\"" % (id)
patchcmd = diffcmd + " | git apply "
tryPatchCmd = patchcmd + "--check -"
applyPatchCmd = patchcmd + "--check --apply -"
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 0e87e0915..55fe8d56c 100644
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+# This is a shell library to calculate the remote repository and
+# upstream branch that should be pulled by "git pull" from the current
+# branch.
# git-ls-remote could be called from outside a git managed repository;
# this would fail in that case and would issue an error message.
diff --git a/git-pull.sh b/git-pull.sh
index b946fd975..97716b885 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -172,7 +172,7 @@ error_on_no_merge_candidates () {
do
case "$opt" in
-t|--t|--ta|--tag|--tags)
- echo "Fetching tags only, you probably meant:"
+ echo "It doesn't make sense to pull all tags; you probably meant:"
echo " git fetch --tags"
exit 1
esac
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 34e3102fc..a4f683a5d 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# This shell script fragment is sourced by git-rebase to implement
+# its default, fast, patch-based, non-interactive mode.
#
# Copyright (c) 2010 Junio C Hamano.
#
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 3c6bed9a2..43c19e082 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -1,11 +1,8 @@
-#!/bin/sh
+# This shell script fragment is sourced by git-rebase to implement
+# its interactive mode. "git rebase --interactive" makes it easy
+# to fix up commits in the middle of a series and rearrange commits.
#
# Copyright (c) 2006 Johannes E. Schindelin
-
-# SHORT DESCRIPTION
-#
-# This script makes it easy to fix up commits in the middle of a series,
-# and rearrange commits.
#
# The original idea comes from Eric W. Biederman, in
# http://article.gmane.org/gmane.comp.version-control.git/22407
diff --git a/git-rebase--merge.sh b/git-rebase--merge.sh
index 16d18176e..e7d96de9a 100644
--- a/git-rebase--merge.sh
+++ b/git-rebase--merge.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+# This shell script fragment is sourced by git-rebase to implement
+# its merge-based non-interactive mode that copes well with renamed
+# files.
#
# Copyright (c) 2010 Junio C Hamano.
#
diff --git a/git-sh-i18n.sh b/git-sh-i18n.sh
index 6a27f6813..e6c3116e1 100644
--- a/git-sh-i18n.sh
+++ b/git-sh-i18n.sh
@@ -1,9 +1,8 @@
-#!/bin/sh
+# This shell library is Git's interface to gettext.sh. See po/README
+# for usage instructions.
#
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
#
-# This is Git's interface to gettext.sh. See po/README for usage
-# instructions.
# Export the TEXTDOMAIN* data that we need for Git
TEXTDOMAIN=git
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index ebfe8f7a4..190a5394b 100644
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -1,9 +1,6 @@
-#!/bin/sh
-#
-# This is included in commands that either have to be run from the toplevel
-# of the repository, or with GIT_DIR environment variable properly.
-# If the GIT_DIR does not look like the right correct git-repository,
-# it dies.
+# This shell scriplet is meant to be included by other shell scripts
+# to set up some variables pointing at the normal git directories and
+# a few helper shell functions.
# Having this variable in your environment would break scripts because
# you would cause "cd" to be taken to unexpected places. If you
diff --git a/git.c b/git.c
index cb5208de6..727e380e5 100644
--- a/git.c
+++ b/git.c
@@ -408,7 +408,6 @@ static void handle_internal_command(int argc, const char **argv)
{ "pack-redundant", cmd_pack_redundant, RUN_SETUP },
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
{ "patch-id", cmd_patch_id },
- { "peek-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
{ "pickaxe", cmd_blame, RUN_SETUP },
{ "prune", cmd_prune, RUN_SETUP },
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
@@ -421,7 +420,6 @@ static void handle_internal_command(int argc, const char **argv)
{ "remote-fd", cmd_remote_fd },
{ "repack", cmd_repack, RUN_SETUP },
{ "replace", cmd_replace, RUN_SETUP },
- { "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
{ "rerere", cmd_rerere, RUN_SETUP },
{ "reset", cmd_reset, RUN_SETUP },
{ "rev-list", cmd_rev_list, RUN_SETUP },
@@ -438,7 +436,6 @@ static void handle_internal_command(int argc, const char **argv)
{ "stripspace", cmd_stripspace },
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
{ "tag", cmd_tag, RUN_SETUP },
- { "tar-tree", cmd_tar_tree },
{ "unpack-file", cmd_unpack_file, RUN_SETUP },
{ "unpack-objects", cmd_unpack_objects, RUN_SETUP },
{ "update-index", cmd_update_index, RUN_SETUP },
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 5cd00d80f..33c3a6c6b 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -156,10 +156,12 @@ proc unmerged_files {files} {
proc parseviewargs {n arglist} {
global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
+ global vinlinediff
global worddiff git_version
set vdatemode($n) 0
set vmergeonly($n) 0
+ set vinlinediff($n) 0
set glflags {}
set diffargs {}
set nextisval 0
@@ -227,12 +229,20 @@ proc parseviewargs {n arglist} {
"--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
"--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
"--remove-empty" - "--first-parent" - "--cherry-pick" -
- "-S*" - "--pickaxe-all" - "--pickaxe-regex" -
+ "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
"--simplify-by-decoration" {
# These mean that we get a subset of the commits
set filtered 1
lappend glflags $arg
}
+ "-L*" {
+ # Line-log with 'stuck' argument (unstuck form is
+ # not supported)
+ set filtered 1
+ set vinlinediff($n) 1
+ set allknown 0
+ lappend glflags $arg
+ }
"-n" {
# This appears to be the only one that has a value as a
# separate word following it
@@ -1704,8 +1714,17 @@ proc parsecommit {id contents listed} {
set comment $newcomment
}
set hasnote [string first "\nNotes:\n" $contents]
+ set diff ""
+ # If there is diff output shown in the git-log stream, split it
+ # out. But get rid of the empty line that always precedes the
+ # diff.
+ set i [string first "\n\ndiff" $comment]
+ if {$i >= 0} {
+ set diff [string range $comment $i+1 end]
+ set comment [string range $comment 0 $i-1]
+ }
set commitinfo($id) [list $headline $auname $audate \
- $comname $comdate $comment $hasnote]
+ $comname $comdate $comment $hasnote $diff]
}
proc getcommit {id} {
@@ -2385,6 +2404,7 @@ proc makewindow {} {
$ctext tag conf found -back $foundbgcolor
$ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
$ctext tag conf wwrap -wrap word
+ $ctext tag conf bold -font textfontbold
.pwbottom add .bleft
if {!$use_ttk} {
@@ -6387,6 +6407,25 @@ proc bindline {t id} {
$canv bind $t <Button-1> "lineclick %x %y $id 1"
}
+proc graph_pane_width {} {
+ global use_ttk
+
+ if {$use_ttk} {
+ set g [.tf.histframe.pwclist sashpos 0]
+ } else {
+ set g [.tf.histframe.pwclist sash coord 0]
+ }
+ return [lindex $g 0]
+}
+
+proc totalwidth {l font extra} {
+ set tot 0
+ foreach str $l {
+ set tot [expr {$tot + [font measure $font $str] + $extra}]
+ }
+ return $tot
+}
+
proc drawtags {id x xt y1} {
global idtags idheads idotherrefs mainhead
global linespc lthickness
@@ -6398,9 +6437,27 @@ proc drawtags {id x xt y1} {
set marks {}
set ntags 0
set nheads 0
+ set singletag 0
+ set maxtags 3
+ set maxtagpct 25
+ set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
+ set delta [expr {int(0.5 * ($linespc - $lthickness))}]
+ set extra [expr {$delta + $lthickness + $linespc}]
+
if {[info exists idtags($id)]} {
set marks $idtags($id)
set ntags [llength $marks]
+ if {$ntags > $maxtags ||
+ [totalwidth $marks mainfont $extra] > $maxwidth} {
+ # show just a single "n tags..." tag
+ set singletag 1
+ if {$ntags == 1} {
+ set marks [list "tag..."]
+ } else {
+ set marks [list [format "%d tags..." $ntags]]
+ }
+ set ntags 1
+ }
}
if {[info exists idheads($id)]} {
set marks [concat $marks $idheads($id)]
@@ -6413,7 +6470,6 @@ proc drawtags {id x xt y1} {
return $xt
}
- set delta [expr {int(0.5 * ($linespc - $lthickness))}]
set yt [expr {$y1 - 0.5 * $linespc}]
set yb [expr {$yt + $linespc - 1}]
set xvals {}
@@ -6428,7 +6484,7 @@ proc drawtags {id x xt y1} {
}
lappend xvals $xt
lappend wvals $wid
- set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
+ set xt [expr {$xt + $wid + $extra}]
}
set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
-width $lthickness -fill $reflinecolor -tags tag.$id]
@@ -6444,7 +6500,12 @@ proc drawtags {id x xt y1} {
$xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
-width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
-tags tag.$id]
- $canv bind $t <1> [list showtag $tag_quoted 1]
+ if {$singletag} {
+ set tagclick [list showtags $id 1]
+ } else {
+ set tagclick [list showtag $tag_quoted 1]
+ }
+ $canv bind $t <1> $tagclick
set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
} else {
# draw a head or other ref
@@ -6471,7 +6532,7 @@ proc drawtags {id x xt y1} {
set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
-font $font -tags [list tag.$id text]]
if {$ntags >= 0} {
- $canv bind $t <1> [list showtag $tag_quoted 1]
+ $canv bind $t <1> $tagclick
} elseif {$nheads >= 0} {
$canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
}
@@ -7080,6 +7141,7 @@ proc selectline {l isnew {desired_loc {}}} {
global cmitmode showneartags allcommits
global targetrow targetid lastscrollrows
global autoselect autosellen jump_to_here
+ global vinlinediff
catch {unset pending_select}
$canv delete hover
@@ -7221,6 +7283,8 @@ proc selectline {l isnew {desired_loc {}}} {
init_flist [mc "Comments"]
if {$cmitmode eq "tree"} {
gettree $id
+ } elseif {$vinlinediff($curview) == 1} {
+ showinlinediff $id
} elseif {[llength $olds] <= 1} {
startdiff $id
} else {
@@ -7557,6 +7621,39 @@ proc startdiff {ids} {
}
}
+proc showinlinediff {ids} {
+ global commitinfo commitdata ctext
+ global treediffs
+
+ set info $commitinfo($ids)
+ set diff [lindex $info 7]
+ set difflines [split $diff "\n"]
+
+ initblobdiffvars
+ set treediff {}
+
+ set inhdr 0
+ foreach line $difflines {
+ if {![string compare -length 5 "diff " $line]} {
+ set inhdr 1
+ } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
+ # offset also accounts for the b/ prefix
+ lappend treediff [string range $line 6 end]
+ set inhdr 0
+ }
+ }
+
+ set treediffs($ids) $treediff
+ add_flist $treediff
+
+ $ctext conf -state normal
+ foreach line $difflines {
+ parseblobdiffline $ids $line
+ }
+ maybe_scroll_ctext 1
+ $ctext conf -state disabled
+}
+
# If the filename (name) is under any of the passed filter paths
# then return true to include the file in the listing.
proc path_filter {filter name} {
@@ -7710,15 +7807,25 @@ proc changeworddiff {name ix op} {
reselectline
}
+proc initblobdiffvars {} {
+ global diffencoding targetline diffnparents
+ global diffinhdr currdiffsubmod diffseehere
+ set targetline {}
+ set diffnparents 0
+ set diffinhdr 0
+ set diffencoding [get_path_encoding {}]
+ set currdiffsubmod ""
+ set diffseehere -1
+}
+
proc getblobdiffs {ids} {
global blobdifffd diffids env
- global diffinhdr treediffs
+ global treediffs
global diffcontext
global ignorespace
global worddiff
global limitdiffs vfilelimit curview
- global diffencoding targetline diffnparents
- global git_version currdiffsubmod
+ global git_version
set textconv {}
if {[package vcompare $git_version "1.6.1"] >= 0} {
@@ -7742,13 +7849,9 @@ proc getblobdiffs {ids} {
error_popup [mc "Error getting diffs: %s" $err]
return
}
- set targetline {}
- set diffnparents 0
- set diffinhdr 0
- set diffencoding [get_path_encoding {}]
fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
set blobdifffd($ids) $bdf
- set currdiffsubmod ""
+ initblobdiffvars
filerun $bdf [list getblobdiffline $bdf $diffids]
}
@@ -7814,13 +7917,17 @@ proc makediffhdr {fname ids} {
set diffline 0
}
+proc blobdiffmaybeseehere {ateof} {
+ global diffseehere
+ if {$diffseehere >= 0} {
+ mark_ctext_line [lindex [split $diffseehere .] 0]
+ }
+ maybe_scroll_ctext ateof
+}
+
proc getblobdiffline {bdf ids} {
- global diffids blobdifffd ctext curdiffstart
- global diffnexthead diffnextnote difffilestart
- global ctext_file_names ctext_file_lines
- global diffinhdr treediffs mergemax diffnparents
- global diffencoding jump_to_here targetline diffline currdiffsubmod
- global worddiff
+ global diffids blobdifffd
+ global ctext
set nr 0
$ctext conf -state normal
@@ -7829,212 +7936,220 @@ proc getblobdiffline {bdf ids} {
catch {close $bdf}
return 0
}
- if {![string compare -length 5 "diff " $line]} {
- if {![regexp {^diff (--cc|--git) } $line m type]} {
- set line [encoding convertfrom $line]
- $ctext insert end "$line\n" hunksep
- continue
+ parseblobdiffline $ids $line
+ }
+ $ctext conf -state disabled
+ blobdiffmaybeseehere [eof $bdf]
+ if {[eof $bdf]} {
+ catch {close $bdf}
+ return 0
+ }
+ return [expr {$nr >= 1000? 2: 1}]
+}
+
+proc parseblobdiffline {ids line} {
+ global ctext curdiffstart
+ global diffnexthead diffnextnote difffilestart
+ global ctext_file_names ctext_file_lines
+ global diffinhdr treediffs mergemax diffnparents
+ global diffencoding jump_to_here targetline diffline currdiffsubmod
+ global worddiff diffseehere
+
+ if {![string compare -length 5 "diff " $line]} {
+ if {![regexp {^diff (--cc|--git) } $line m type]} {
+ set line [encoding convertfrom $line]
+ $ctext insert end "$line\n" hunksep
+ continue
+ }
+ # start of a new file
+ set diffinhdr 1
+ $ctext insert end "\n"
+ set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names ""
+ lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
+ $ctext insert end "\n" filesep
+
+ if {$type eq "--cc"} {
+ # start of a new file in a merge diff
+ set fname [string range $line 10 end]
+ if {[lsearch -exact $treediffs($ids) $fname] < 0} {
+ lappend treediffs($ids) $fname
+ add_flist [list $fname]
}
- # start of a new file
- set diffinhdr 1
- $ctext insert end "\n"
- set curdiffstart [$ctext index "end - 1c"]
- lappend ctext_file_names ""
- lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
- $ctext insert end "\n" filesep
-
- if {$type eq "--cc"} {
- # start of a new file in a merge diff
- set fname [string range $line 10 end]
- if {[lsearch -exact $treediffs($ids) $fname] < 0} {
- lappend treediffs($ids) $fname
- add_flist [list $fname]
- }
+ } else {
+ set line [string range $line 11 end]
+ # If the name hasn't changed the length will be odd,
+ # the middle char will be a space, and the two bits either
+ # side will be a/name and b/name, or "a/name" and "b/name".
+ # If the name has changed we'll get "rename from" and
+ # "rename to" or "copy from" and "copy to" lines following
+ # this, and we'll use them to get the filenames.
+ # This complexity is necessary because spaces in the
+ # filename(s) don't get escaped.
+ set l [string length $line]
+ set i [expr {$l / 2}]
+ if {!(($l & 1) && [string index $line $i] eq " " &&
+ [string range $line 2 [expr {$i - 1}]] eq \
+ [string range $line [expr {$i + 3}] end])} {
+ return
+ }
+ # unescape if quoted and chop off the a/ from the front
+ if {[string index $line 0] eq "\""} {
+ set fname [string range [lindex $line 0] 2 end]
} else {
- set line [string range $line 11 end]
- # If the name hasn't changed the length will be odd,
- # the middle char will be a space, and the two bits either
- # side will be a/name and b/name, or "a/name" and "b/name".
- # If the name has changed we'll get "rename from" and
- # "rename to" or "copy from" and "copy to" lines following
- # this, and we'll use them to get the filenames.
- # This complexity is necessary because spaces in the
- # filename(s) don't get escaped.
- set l [string length $line]
- set i [expr {$l / 2}]
- if {!(($l & 1) && [string index $line $i] eq " " &&
- [string range $line 2 [expr {$i - 1}]] eq \
- [string range $line [expr {$i + 3}] end])} {
- continue
- }
- # unescape if quoted and chop off the a/ from the front
- if {[string index $line 0] eq "\""} {
- set fname [string range [lindex $line 0] 2 end]
- } else {
- set fname [string range $line 2 [expr {$i - 1}]]
- }
+ set fname [string range $line 2 [expr {$i - 1}]]
}
- makediffhdr $fname $ids
+ }
+ makediffhdr $fname $ids
+
+ } elseif {![string compare -length 16 "* Unmerged path " $line]} {
+ set fname [encoding convertfrom [string range $line 16 end]]
+ $ctext insert end "\n"
+ set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names $fname
+ lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
+ $ctext insert end "$line\n" filesep
+ set i [lsearch -exact $treediffs($ids) $fname]
+ if {$i >= 0} {
+ setinlist difffilestart $i $curdiffstart
+ }
- } elseif {![string compare -length 16 "* Unmerged path " $line]} {
- set fname [encoding convertfrom [string range $line 16 end]]
- $ctext insert end "\n"
- set curdiffstart [$ctext index "end - 1c"]
- lappend ctext_file_names $fname
- lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
+ } elseif {![string compare -length 2 "@@" $line]} {
+ regexp {^@@+} $line ats
+ set line [encoding convertfrom $diffencoding $line]
+ $ctext insert end "$line\n" hunksep
+ if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
+ set diffline $nl
+ }
+ set diffnparents [expr {[string length $ats] - 1}]
+ set diffinhdr 0
+
+ } elseif {![string compare -length 10 "Submodule " $line]} {
+ # start of a new submodule
+ if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
+ set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
+ } else {
+ set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
+ }
+ if {$currdiffsubmod != $fname} {
+ $ctext insert end "\n"; # Add newline after commit message
+ }
+ set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names ""
+ if {$currdiffsubmod != $fname} {
+ lappend ctext_file_lines $fname
+ makediffhdr $fname $ids
+ set currdiffsubmod $fname
+ $ctext insert end "\n$line\n" filesep
+ } else {
$ctext insert end "$line\n" filesep
+ }
+ } elseif {![string compare -length 3 " >" $line]} {
+ set $currdiffsubmod ""
+ set line [encoding convertfrom $diffencoding $line]
+ $ctext insert end "$line\n" dresult
+ } elseif {![string compare -length 3 " <" $line]} {
+ set $currdiffsubmod ""
+ set line [encoding convertfrom $diffencoding $line]
+ $ctext insert end "$line\n" d0
+ } elseif {$diffinhdr} {
+ if {![string compare -length 12 "rename from " $line]} {
+ set fname [string range $line [expr 6 + [string first " from " $line] ] end]
+ if {[string index $fname 0] eq "\""} {
+ set fname [lindex $fname 0]
+ }
+ set fname [encoding convertfrom $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
-
- } elseif {![string compare -length 2 "@@" $line]} {
- regexp {^@@+} $line ats
- set line [encoding convertfrom $diffencoding $line]
- $ctext insert end "$line\n" hunksep
- if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
- set diffline $nl
+ } elseif {![string compare -length 10 $line "rename to "] ||
+ ![string compare -length 8 $line "copy to "]} {
+ set fname [string range $line [expr 4 + [string first " to " $line] ] end]
+ if {[string index $fname 0] eq "\""} {
+ set fname [lindex $fname 0]
}
- set diffnparents [expr {[string length $ats] - 1}]
+ makediffhdr $fname $ids
+ } elseif {[string compare -length 3 $line "---"] == 0} {
+ # do nothing
+ return
+ } elseif {[string compare -length 3 $line "+++"] == 0} {
set diffinhdr 0
+ return
+ }
+ $ctext insert end "$line\n" filesep
- } elseif {![string compare -length 10 "Submodule " $line]} {
- # start of a new submodule
- if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
- set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
- } else {
- set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
- }
- if {$currdiffsubmod != $fname} {
- $ctext insert end "\n"; # Add newline after commit message
- }
- set curdiffstart [$ctext index "end - 1c"]
- lappend ctext_file_names ""
- if {$currdiffsubmod != $fname} {
- lappend ctext_file_lines $fname
- makediffhdr $fname $ids
- set currdiffsubmod $fname
- $ctext insert end "\n$line\n" filesep
- } else {
- $ctext insert end "$line\n" filesep
- }
- } elseif {![string compare -length 3 " >" $line]} {
- set $currdiffsubmod ""
- set line [encoding convertfrom $diffencoding $line]
- $ctext insert end "$line\n" dresult
- } elseif {![string compare -length 3 " <" $line]} {
- set $currdiffsubmod ""
- set line [encoding convertfrom $diffencoding $line]
- $ctext insert end "$line\n" d0
- } elseif {$diffinhdr} {
- if {![string compare -length 12 "rename from " $line]} {
- set fname [string range $line [expr 6 + [string first " from " $line] ] end]
- if {[string index $fname 0] eq "\""} {
- set fname [lindex $fname 0]
- }
- set fname [encoding convertfrom $fname]
- set i [lsearch -exact $treediffs($ids) $fname]
- if {$i >= 0} {
- setinlist difffilestart $i $curdiffstart
+ } else {
+ set line [string map {\x1A ^Z} \
+ [encoding convertfrom $diffencoding $line]]
+ # parse the prefix - one ' ', '-' or '+' for each parent
+ set prefix [string range $line 0 [expr {$diffnparents - 1}]]
+ set tag [expr {$diffnparents > 1? "m": "d"}]
+ set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
+ set words_pre_markup ""
+ set words_post_markup ""
+ if {[string trim $prefix " -+"] eq {}} {
+ # prefix only has " ", "-" and "+" in it: normal diff line
+ set num [string first "-" $prefix]
+ if {$dowords} {
+ set line [string range $line 1 end]
+ }
+ if {$num >= 0} {
+ # removed line, first parent with line is $num
+ if {$num >= $mergemax} {
+ set num "max"
}
- } elseif {![string compare -length 10 $line "rename to "] ||
- ![string compare -length 8 $line "copy to "]} {
- set fname [string range $line [expr 4 + [string first " to " $line] ] end]
- if {[string index $fname 0] eq "\""} {
- set fname [lindex $fname 0]
+ if {$dowords && $worddiff eq [mc "Markup words"]} {
+ $ctext insert end "\[-$line-\]" $tag$num
+ } else {
+ $ctext insert end "$line" $tag$num
}
- makediffhdr $fname $ids
- } elseif {[string compare -length 3 $line "---"] == 0} {
- # do nothing
- continue
- } elseif {[string compare -length 3 $line "+++"] == 0} {
- set diffinhdr 0
- continue
- }
- $ctext insert end "$line\n" filesep
-
- } else {
- set line [string map {\x1A ^Z} \
- [encoding convertfrom $diffencoding $line]]
- # parse the prefix - one ' ', '-' or '+' for each parent
- set prefix [string range $line 0 [expr {$diffnparents - 1}]]
- set tag [expr {$diffnparents > 1? "m": "d"}]
- set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
- set words_pre_markup ""
- set words_post_markup ""
- if {[string trim $prefix " -+"] eq {}} {
- # prefix only has " ", "-" and "+" in it: normal diff line
- set num [string first "-" $prefix]
- if {$dowords} {
- set line [string range $line 1 end]
+ if {!$dowords} {
+ $ctext insert end "\n" $tag$num
}
- if {$num >= 0} {
- # removed line, first parent with line is $num
- if {$num >= $mergemax} {
- set num "max"
- }
- if {$dowords && $worddiff eq [mc "Markup words"]} {
- $ctext insert end "\[-$line-\]" $tag$num
- } else {
- $ctext insert end "$line" $tag$num
- }
- if {!$dowords} {
- $ctext insert end "\n" $tag$num
- }
- } else {
- set tags {}
- if {[string first "+" $prefix] >= 0} {
- # added line
- lappend tags ${tag}result
- if {$diffnparents > 1} {
- set num [string first " " $prefix]
- if {$num >= 0} {
- if {$num >= $mergemax} {
- set num "max"
- }
- lappend tags m$num
+ } else {
+ set tags {}
+ if {[string first "+" $prefix] >= 0} {
+ # added line
+ lappend tags ${tag}result
+ if {$diffnparents > 1} {
+ set num [string first " " $prefix]
+ if {$num >= 0} {
+ if {$num >= $mergemax} {
+ set num "max"
}
+ lappend tags m$num
}
- set words_pre_markup "{+"
- set words_post_markup "+}"
}
- if {$targetline ne {}} {
- if {$diffline == $targetline} {
- set seehere [$ctext index "end - 1 chars"]
- set targetline {}
- } else {
- incr diffline
- }
- }
- if {$dowords && $worddiff eq [mc "Markup words"]} {
- $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
+ set words_pre_markup "{+"
+ set words_post_markup "+}"
+ }
+ if {$targetline ne {}} {
+ if {$diffline == $targetline} {
+ set diffseehere [$ctext index "end - 1 chars"]
+ set targetline {}
} else {
- $ctext insert end "$line" $tags
- }
- if {!$dowords} {
- $ctext insert end "\n" $tags
+ incr diffline
}
}
- } elseif {$dowords && $prefix eq "~"} {
- $ctext insert end "\n" {}
- } else {
- # "\ No newline at end of file",
- # or something else we don't recognize
- $ctext insert end "$line\n" hunksep
+ if {$dowords && $worddiff eq [mc "Markup words"]} {
+ $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
+ } else {
+ $ctext insert end "$line" $tags
+ }
+ if {!$dowords} {
+ $ctext insert end "\n" $tags
+ }
}
+ } elseif {$dowords && $prefix eq "~"} {
+ $ctext insert end "\n" {}
+ } else {
+ # "\ No newline at end of file",
+ # or something else we don't recognize
+ $ctext insert end "$line\n" hunksep
}
}
- if {[info exists seehere]} {
- mark_ctext_line [lindex [split $seehere .] 0]
- }
- maybe_scroll_ctext [eof $bdf]
- $ctext conf -state disabled
- if {[eof $bdf]} {
- catch {close $bdf}
- return 0
- }
- return [expr {$nr >= 1000? 2: 1}]
}
proc changediffdisp {} {
@@ -10878,6 +10993,23 @@ proc listrefs {id} {
return [list $x $y $z]
}
+proc add_tag_ctext {tag} {
+ global ctext cached_tagcontent tagids
+
+ if {![info exists cached_tagcontent($tag)]} {
+ catch {
+ set cached_tagcontent($tag) [exec git cat-file -p $tag]
+ }
+ }
+ $ctext insert end "[mc "Tag"]: $tag\n" bold
+ if {[info exists cached_tagcontent($tag)]} {
+ set text $cached_tagcontent($tag)
+ } else {
+ set text "[mc "Id"]: $tagids($tag)"
+ }
+ appendwithlinks $text {}
+}
+
proc showtag {tag isnew} {
global ctext cached_tagcontent tagids linknum tagobjid
@@ -10888,17 +11020,28 @@ proc showtag {tag isnew} {
clear_ctext
settabs 0
set linknum 0
- if {![info exists cached_tagcontent($tag)]} {
- catch {
- set cached_tagcontent($tag) [exec git cat-file -p $tag]
- }
+ add_tag_ctext $tag
+ maybe_scroll_ctext 1
+ $ctext conf -state disabled
+ init_flist {}
+}
+
+proc showtags {id isnew} {
+ global idtags ctext linknum
+
+ if {$isnew} {
+ addtohistory [list showtags $id 0] savectextpos
}
- if {[info exists cached_tagcontent($tag)]} {
- set text $cached_tagcontent($tag)
- } else {
- set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
+ $ctext conf -state normal
+ clear_ctext
+ settabs 0
+ set linknum 0
+ set sep {}
+ foreach tag $idtags($id) {
+ $ctext insert end $sep
+ add_tag_ctext $tag
+ set sep "\n\n"
}
- appendwithlinks $text {}
maybe_scroll_ctext 1
$ctext conf -state disabled
init_flist {}
diff --git a/remote.c b/remote.c
index 9f1a8aa2c..15e6e5efc 100644
--- a/remote.c
+++ b/remote.c
@@ -745,35 +745,66 @@ int for_each_remote(each_remote_fn fn, void *priv)
return result;
}
-void ref_remove_duplicates(struct ref *ref_map)
+static void handle_duplicate(struct ref *ref1, struct ref *ref2)
+{
+ if (strcmp(ref1->name, ref2->name)) {
+ if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
+ ref2->fetch_head_status != FETCH_HEAD_IGNORE) {
+ die(_("Cannot fetch both %s and %s to %s"),
+ ref1->name, ref2->name, ref2->peer_ref->name);
+ } else if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
+ ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
+ warning(_("%s usually tracks %s, not %s"),
+ ref2->peer_ref->name, ref2->name, ref1->name);
+ } else if (ref1->fetch_head_status == FETCH_HEAD_IGNORE &&
+ ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
+ die(_("%s tracks both %s and %s"),
+ ref2->peer_ref->name, ref1->name, ref2->name);
+ } else {
+ /*
+ * This last possibility doesn't occur because
+ * FETCH_HEAD_IGNORE entries always appear at
+ * the end of the list.
+ */
+ die(_("Internal error"));
+ }
+ }
+ free(ref2->peer_ref);
+ free(ref2);
+}
+
+struct ref *ref_remove_duplicates(struct ref *ref_map)
{
struct string_list refs = STRING_LIST_INIT_NODUP;
- struct string_list_item *item = NULL;
- struct ref *prev = NULL, *next = NULL;
- for (; ref_map; prev = ref_map, ref_map = next) {
- next = ref_map->next;
- if (!ref_map->peer_ref)
- continue;
+ struct ref *retval = NULL;
+ struct ref **p = &retval;
- item = string_list_lookup(&refs, ref_map->peer_ref->name);
- if (item) {
- if (strcmp(((struct ref *)item->util)->name,
- ref_map->name))
- die("%s tracks both %s and %s",
- ref_map->peer_ref->name,
- ((struct ref *)item->util)->name,
- ref_map->name);
- prev->next = ref_map->next;
- free(ref_map->peer_ref);
- free(ref_map);
- ref_map = prev; /* skip this; we freed it */
- continue;
- }
+ while (ref_map) {
+ struct ref *ref = ref_map;
+
+ ref_map = ref_map->next;
+ ref->next = NULL;
- item = string_list_insert(&refs, ref_map->peer_ref->name);
- item->util = ref_map;
+ if (!ref->peer_ref) {
+ *p = ref;
+ p = &ref->next;
+ } else {
+ struct string_list_item *item =
+ string_list_insert(&refs, ref->peer_ref->name);
+
+ if (item->util) {
+ /* Entry already existed */
+ handle_duplicate((struct ref *)item->util, ref);
+ } else {
+ *p = ref;
+ p = &ref->next;
+ item->util = ref;
+ }
+ }
}
+
string_list_clear(&refs, 0);
+ return retval;
}
int remote_has_url(struct remote *remote, const char *url)
@@ -825,6 +856,8 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
{
int i;
int find_src = !query->src;
+ const char *needle = find_src ? query->dst : query->src;
+ char **result = find_src ? &query->src : &query->dst;
if (find_src && !query->dst)
return error("query_refspecs: need either src or dst");
@@ -833,8 +866,6 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
struct refspec *refspec = &refs[i];
const char *key = find_src ? refspec->dst : refspec->src;
const char *value = find_src ? refspec->src : refspec->dst;
- const char *needle = find_src ? query->dst : query->src;
- char **result = find_src ? &query->src : &query->dst;
if (!refspec->dst)
continue;
@@ -1553,6 +1584,13 @@ static int ignore_symref_update(const char *refname)
return (flag & REF_ISSYMREF);
}
+/*
+ * Create and return a list of (struct ref) consisting of copies of
+ * each remote_ref that matches refspec. refspec must be a pattern.
+ * Fill in the copies' peer_ref to describe the local tracking refs to
+ * which they map. Omit any references that would map to an existing
+ * local symbolic ref.
+ */
static struct ref *get_expanded_map(const struct ref *remote_refs,
const struct refspec *refspec)
{
@@ -1560,9 +1598,9 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
struct ref *ret = NULL;
struct ref **tail = &ret;
- char *expn_name;
-
for (ref = remote_refs; ref; ref = ref->next) {
+ char *expn_name = NULL;
+
if (strchr(ref->name, '^'))
continue; /* a dereference item */
if (match_name_with_pattern(refspec->src, ref->name,
@@ -1571,12 +1609,12 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
struct ref *cpy = copy_ref(ref);
cpy->peer_ref = alloc_ref(expn_name);
- free(expn_name);
if (refspec->force)
cpy->peer_ref->force = 1;
*tail = cpy;
tail = &cpy->next;
}
+ free(expn_name);
}
return ret;
diff --git a/remote.h b/remote.h
index 131130a61..c07eb9950 100644
--- a/remote.h
+++ b/remote.h
@@ -149,9 +149,13 @@ int resolve_remote_symref(struct ref *ref, struct ref *list);
int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1);
/*
- * Removes and frees any duplicate refs in the map.
+ * Remove and free all but the first of any entries in the input list
+ * that map the same remote reference to the same local reference. If
+ * there are two entries that map different remote references to the
+ * same local reference, emit an error message and die. Return a
+ * pointer to the head of the resulting list.
*/
-void ref_remove_duplicates(struct ref *ref_map);
+struct ref *ref_remove_duplicates(struct ref *ref_map);
int valid_fetch_refspec(const char *refspec);
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
diff --git a/send-pack.c b/send-pack.c
index fab62e3da..9ee8cf50a 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -206,6 +206,8 @@ int send_pack(struct send_pack_args *args,
quiet_supported = 1;
if (server_supports("agent"))
agent_supported = 1;
+ if (server_supports("no-thin"))
+ args->use_thin_pack = 0;
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
diff --git a/t/Git-SVN/00compile.t b/t/Git-SVN/00compile.t
index c92fee453..c92fee453 100644..100755
--- a/t/Git-SVN/00compile.t
+++ b/t/Git-SVN/00compile.t
diff --git a/t/Git-SVN/Utils/add_path_to_url.t b/t/Git-SVN/Utils/add_path_to_url.t
index bfbd87845..bfbd87845 100644..100755
--- a/t/Git-SVN/Utils/add_path_to_url.t
+++ b/t/Git-SVN/Utils/add_path_to_url.t
diff --git a/t/Git-SVN/Utils/can_compress.t b/t/Git-SVN/Utils/can_compress.t
index d7b49b8d5..d7b49b8d5 100644..100755
--- a/t/Git-SVN/Utils/can_compress.t
+++ b/t/Git-SVN/Utils/can_compress.t
diff --git a/t/Git-SVN/Utils/canonicalize_url.t b/t/Git-SVN/Utils/canonicalize_url.t
index 05795ab63..05795ab63 100644..100755
--- a/t/Git-SVN/Utils/canonicalize_url.t
+++ b/t/Git-SVN/Utils/canonicalize_url.t
diff --git a/t/Git-SVN/Utils/collapse_dotdot.t b/t/Git-SVN/Utils/collapse_dotdot.t
index 1da1cce15..1da1cce15 100644..100755
--- a/t/Git-SVN/Utils/collapse_dotdot.t
+++ b/t/Git-SVN/Utils/collapse_dotdot.t
diff --git a/t/Git-SVN/Utils/fatal.t b/t/Git-SVN/Utils/fatal.t
index 49e143829..49e143829 100644..100755
--- a/t/Git-SVN/Utils/fatal.t
+++ b/t/Git-SVN/Utils/fatal.t
diff --git a/t/Git-SVN/Utils/join_paths.t b/t/Git-SVN/Utils/join_paths.t
index d4488e716..d4488e716 100644..100755
--- a/t/Git-SVN/Utils/join_paths.t
+++ b/t/Git-SVN/Utils/join_paths.t
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
index 8cf909a6c..d5dab5a94 100644
--- a/t/gitweb-lib.sh
+++ b/t/gitweb-lib.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Initialization and helpers for Gitweb tests, which source this
+# shell library instead of test-lib.sh.
#
# Copyright (c) 2007 Jakub Narebski
#
diff --git a/t/lib-bash.sh b/t/lib-bash.sh
index 11397f747..2be955faf 100644
--- a/t/lib-bash.sh
+++ b/t/lib-bash.sh
@@ -1,7 +1,6 @@
-#!/bin/sh
-#
-# Ensures that tests are run under Bash; primarily intended for running tests
-# of the completion script.
+# Shell library sourced instead of ./test-lib.sh by tests that need
+# to run under Bash; primarily intended for tests of the completion
+# script.
if test -n "$BASH" && test -z "$POSIXLY_CORRECT"; then
# we are in full-on bash mode
diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh
index 44263ade2..507671891 100644
--- a/t/lib-cvs.sh
+++ b/t/lib-cvs.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Shell library sourced instead of ./test-lib.sh by cvsimport tests.
. ./test-lib.sh
diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh
index 75ffd9174..8b4dbf22d 100644
--- a/t/lib-diff-alternative.sh
+++ b/t/lib-diff-alternative.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Helpers shared by the test scripts for diff algorithms (patience,
+# histogram, etc).
test_diff_frobnitz() {
cat >file1 <<\EOF
diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh
index ae8883a07..eec757f10 100644
--- a/t/lib-gettext.sh
+++ b/t/lib-gettext.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Initialization and Icelandic locale for basic git i18n tests,
+# which source this scriptlet instead of ./test-lib.sh.
#
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
#
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index 87f0ad8f4..394b06b32 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -1,4 +1,20 @@
-#!/bin/sh
+# Shell library to run git-daemon in tests. Ends the test early if
+# GIT_TEST_GIT_DAEMON is not set.
+#
+# Usage:
+#
+# . ./test-lib.sh
+# . "$TEST_DIRECTORY"/lib-git-daemon.sh
+# start_git_daemon
+#
+# test_expect_success '...' '
+# ...
+# '
+#
+# test_expect_success ...
+#
+# stop_git_daemon
+# test_done
if test -z "$GIT_TEST_GIT_DAEMON"
then
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index ad8f1ef71..c4707843c 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -1,4 +1,31 @@
-#!/bin/sh
+# Shell library to run an HTTP server for use in tests.
+# Ends the test early if httpd tests should not be run,
+# for example because the user has not enabled them.
+#
+# Usage:
+#
+# . ./test-lib.sh
+# . "$TEST_DIRECTORY"/lib-httpd.sh
+# start_httpd
+#
+# test_expect_success '...' '
+# ...
+# '
+#
+# test_expect_success ...
+#
+# stop_httpd
+# test_done
+#
+# Can be configured using the following variables.
+#
+# GIT_TEST_HTTPD enable HTTPD tests
+# LIB_HTTPD_PATH web server path
+# LIB_HTTPD_MODULE_PATH web server modules path
+# LIB_HTTPD_PORT listening port
+# LIB_HTTPD_DAV enable DAV
+# LIB_HTTPD_SVN enable SVN
+# LIB_HTTPD_SSL enable SSL
#
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
#
diff --git a/t/lib-pack.sh b/t/lib-pack.sh
index b96e1254d..750984657 100644
--- a/t/lib-pack.sh
+++ b/t/lib-pack.sh
@@ -1,5 +1,3 @@
-#!/bin/sh
-#
# Support routines for hand-crafting weird or malicious packs.
#
# You can make a complete pack like:
diff --git a/t/lib-pager.sh b/t/lib-pager.sh
index ba03eab14..3aa7a3ffd 100644
--- a/t/lib-pager.sh
+++ b/t/lib-pager.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Helpers for tests of git's choice of pager.
test_expect_success 'determine default pager' '
test_might_fail git config --unset core.pager &&
diff --git a/t/lib-prereq-FILEMODE.sh b/t/lib-prereq-FILEMODE.sh
deleted file mode 100644
index bce5a4c8b..000000000
--- a/t/lib-prereq-FILEMODE.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
-#
-
-if test "$(git config --bool core.filemode)" = false
-then
- say 'filemode disabled on the filesystem'
-else
- test_set_prereq FILEMODE
-fi
diff --git a/t/lib-read-tree.sh b/t/lib-read-tree.sh
index ef079afc4..b95f48560 100644
--- a/t/lib-read-tree.sh
+++ b/t/lib-read-tree.sh
@@ -1,5 +1,3 @@
-#!/bin/sh
-#
# Helper functions to check if read-tree would succeed/fail as expected with
# and without the dry-run option. They also test that the dry-run does not
# write the index and that together with -u it doesn't touch the work tree.
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 8ff87fb3f..6bd252212 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Helper functions used by interactive rebase tests.
# After setting the fake editor with this function, you can
#
diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh
index 737df289a..9a2dca506 100644
--- a/t/lib-terminal.sh
+++ b/t/lib-terminal.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Helpers for terminal output tests.
test_expect_success PERL 'set up terminal for tests' '
# Reading from the pty master seems to get stuck _sometimes_
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index f4eecaa17..a8c957429 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+# Performance testing framework. Each perf script starts much like
+# a normal test script, except it sources this library instead of
+# test-lib.sh. See t/perf/README for documentation.
#
# Copyright (c) 2011 Thomas Rast
#
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
index 2c10cb469..2c10cb469 100644..100755
--- a/t/t0202/test.pl
+++ b/t/t0202/test.pl
diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh
index 46103a159..3a2c81968 100755
--- a/t/t1303-wacky-config.sh
+++ b/t/t1303-wacky-config.sh
@@ -3,17 +3,28 @@
test_description='Test wacky input to git config'
. ./test-lib.sh
+# Leaving off the newline is intentional!
setup() {
(printf "[section]\n" &&
printf " key = foo") >.git/config
}
+# 'check section.key value' verifies that the entry for section.key is
+# 'value'
check() {
echo "$2" >expected
git config --get "$1" >actual 2>&1
test_cmp actual expected
}
+# 'check section.key regex value' verifies that the entry for
+# section.key *that matches 'regex'* is 'value'
+check_regex() {
+ echo "$3" >expected
+ git config --get "$1" "$2" >actual 2>&1
+ test_cmp actual expected
+}
+
test_expect_success 'modify same key' '
setup &&
git config section.key bar &&
@@ -47,4 +58,57 @@ test_expect_success 'do not crash on special long config line' '
check section.key "$LONG_VALUE"
'
+setup_many() {
+ setup &&
+ # This time we want the newline so that we can tack on more
+ # entries.
+ echo >>.git/config &&
+ # Semi-efficient way of concatenating 5^5 = 3125 lines. Note
+ # that because 'setup' already put one line, this means 3126
+ # entries for section.key in the config file.
+ cat >5to1 <<-\EOF &&
+ key = foo
+ key = foo
+ key = foo
+ key = foo
+ key = foo
+ EOF
+ cat 5to1 5to1 5to1 5to1 5to1 >5to2 && # 25
+ cat 5to2 5to2 5to2 5to2 5to2 >5to3 && # 125
+ cat 5to3 5to3 5to3 5to3 5to3 >5to4 && # 635
+ cat 5to4 5to4 5to4 5to4 5to4 >>.git/config # 3125
+}
+
+test_expect_success 'get many entries' '
+ setup_many &&
+ git config --get-all section.key >actual &&
+ test_line_count = 3126 actual
+'
+
+test_expect_success 'get many entries by regex' '
+ setup_many &&
+ git config --get-regexp "sec.*ke." >actual &&
+ test_line_count = 3126 actual
+'
+
+test_expect_success 'add and replace one of many entries' '
+ setup_many &&
+ git config --add section.key bar &&
+ check_regex section.key "b.*r" bar &&
+ git config section.key beer "b.*r" &&
+ check_regex section.key "b.*r" beer
+'
+
+test_expect_success 'replace many entries' '
+ setup_many &&
+ git config --replace-all section.key bar &&
+ check section.key bar
+'
+
+test_expect_success 'unset many entries' '
+ setup_many &&
+ git config --unset-all section.key &&
+ test_must_fail git config section.key
+'
+
test_done
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 9dc91d09d..24ddd8a70 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -2,7 +2,6 @@
test_description='add -i basic tests'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
if ! test_have_prereq PERL
then
diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh
index e3ea3d511..49e2d6c34 100755
--- a/t/t4102-apply-rename.sh
+++ b/t/t4102-apply-rename.sh
@@ -7,7 +7,6 @@ test_description='git apply handling copy/rename patch.
'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
# setup
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index 2298ece80..1e4d4380b 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -48,12 +48,12 @@ test_expect_success 'apply in reverse' '
test_expect_success 'setup separate repository lacking postimage' '
- git tar-tree initial initial | $TAR xf - &&
+ git archive --format=tar --prefix=initial/ initial | $TAR xf - &&
(
cd initial && git init && git add .
) &&
- git tar-tree second second | $TAR xf - &&
+ git archive --format=tar --prefix=second/ second | $TAR xf - &&
(
cd second && git init && git add .
)
diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh
index c5fecdfed..497b62868 100755
--- a/t/t4120-apply-popt.sh
+++ b/t/t4120-apply-popt.sh
@@ -6,7 +6,6 @@
test_description='git apply -p handling.'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success setup '
mkdir sub &&
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index 0d36ebdc8..c268298ea 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -3,7 +3,6 @@
test_description='applying patch with mode bits'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success setup '
echo original >file &&
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index c2023b1a3..05f011d38 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -3,7 +3,7 @@
# Copyright (C) 2005 Rene Scharfe
#
-test_description='git tar-tree and git get-tar-commit-id test
+test_description='git archive and git get-tar-commit-id test
This test covers the topics of file contents, commit date handling and
commit id embedding:
@@ -13,11 +13,11 @@ commit id embedding:
binary file (/bin/sh). Only paths shorter than 99 characters are
used.
- git tar-tree applies the commit date to every file in the archive it
+ git archive applies the commit date to every file in the archive it
creates. The test sets the commit date to a specific value and checks
if the tar archive contains that value.
- When giving git tar-tree a commit id (in contrast to a tree id) it
+ When giving git archive a commit id (in contrast to a tree id) it
embeds this commit id into the tar archive as a comment. The test
checks the ability of git get-tar-commit-id to figure it out from the
tar file.
@@ -25,8 +25,6 @@ commit id embedding:
'
. ./test-lib.sh
-GZIP=${GZIP:-gzip}
-GUNZIP=${GUNZIP:-gzip -d}
SUBSTFORMAT=%H%n
@@ -39,6 +37,8 @@ test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
)
'
+test_lazy_prereq GZIP 'gzip --version'
+
get_pax_header() {
file=$1
header=$2=
@@ -196,16 +196,6 @@ test_expect_success \
'git get-tar-commit-id <b.tar >b.commitid &&
test_cmp .git/$(git symbolic-ref HEAD) b.commitid'
-test_expect_success 'git tar-tree' '
- git tar-tree HEAD >tar-tree.tar &&
- test_cmp b.tar tar-tree.tar
-'
-
-test_expect_success 'git tar-tree with prefix' '
- git tar-tree HEAD prefix >tar-tree_with_prefix.tar &&
- test_cmp with_prefix.tar tar-tree_with_prefix.tar
-'
-
test_expect_success 'git archive with --output, override inferred format' '
git archive --format=tar --output=d4.zip HEAD &&
test_cmp b.tar d4.zip
@@ -275,12 +265,6 @@ test_expect_success 'only enabled filters are available remotely' '
test_cmp remote.bar config.bar
'
-if $GZIP --version >/dev/null 2>&1; then
- test_set_prereq GZIP
-else
- say "Skipping some tar.gz tests because gzip not found"
-fi
-
test_expect_success GZIP 'git archive --format=tgz' '
git archive --format=tgz HEAD >j.tgz
'
@@ -300,14 +284,8 @@ test_expect_success GZIP 'infer tgz from .tar.gz filename' '
test_cmp j.tgz j3.tar.gz
'
-if $GUNZIP --version >/dev/null 2>&1; then
- test_set_prereq GUNZIP
-else
- say "Skipping some tar.gz tests because gunzip was not found"
-fi
-
-test_expect_success GZIP,GUNZIP 'extract tgz file' '
- $GUNZIP -c <j.tgz >j.tar &&
+test_expect_success GZIP 'extract tgz file' '
+ gzip -d -c <j.tgz >j.tar &&
test_cmp b.tar j.tar
'
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index f47d8717f..51dedab29 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -87,14 +87,4 @@ test_expect_success 'export-subst' '
test_cmp substfile2 archive/substfile2
'
-test_expect_success 'git tar-tree vs. git archive with worktree attributes' '
- git tar-tree HEAD >tar-tree.tar &&
- test_cmp worktree.tar tar-tree.tar
-'
-
-test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' '
- (cd bare && git tar-tree HEAD) >bare-tar-tree.tar &&
- test_cmp bare-worktree.tar bare-tar-tree.tar
-'
-
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 1f0f8e682..5d4581dac 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -88,7 +88,7 @@ test_expect_success 'fetch --prune on its own works as expected' '
cd "$D" &&
git clone . prune &&
cd prune &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin &&
test_must_fail git rev-parse origin/extrabranch
@@ -98,7 +98,7 @@ test_expect_success 'fetch --prune with a branch name keeps branches' '
cd "$D" &&
git clone . prune-branch &&
cd prune-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin master &&
git rev-parse origin/extrabranch
@@ -113,25 +113,45 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
git rev-parse origin/master
'
-test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
+test_expect_success 'fetch --prune --tags prunes branches but not tags' '
cd "$D" &&
git clone . prune-tags &&
cd prune-tags &&
- git fetch origin refs/heads/master:refs/tags/sometag &&
+ git tag sometag master &&
+ # Create what looks like a remote-tracking branch from an earlier
+ # fetch that has since been deleted from the remote:
+ git update-ref refs/remotes/origin/fake-remote master &&
git fetch --prune --tags origin &&
git rev-parse origin/master &&
- test_must_fail git rev-parse somebranch
+ test_must_fail git rev-parse origin/fake-remote &&
+ git rev-parse sometag
'
-test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
+test_expect_success 'fetch --prune --tags with branch does not prune other things' '
cd "$D" &&
git clone . prune-tags-branch &&
cd prune-tags-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git tag sometag master &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune --tags origin master &&
- git rev-parse origin/extrabranch
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
+'
+
+test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
+ cd "$D" &&
+ git clone . prune-tags-refspec &&
+ cd prune-tags-refspec &&
+ git tag sometag master &&
+ git update-ref refs/remotes/origin/foo/otherbranch master &&
+ git update-ref refs/remotes/origin/extrabranch master &&
+
+ git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+ test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
'
test_expect_success 'fetch tags when there is no tags' '
diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git
index 1669cc4af..0f70f66c7 100644
--- a/t/t5515/fetch.br-unconfig_--tags_.._.git
+++ b/t/t5515/fetch.br-unconfig_--tags_.._.git
@@ -1,4 +1,5 @@
# br-unconfig --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git
index 8a7493537..ab473a6e1 100644
--- a/t/t5515/fetch.master_--tags_.._.git
+++ b/t/t5515/fetch.master_--tags_.._.git
@@ -1,4 +1,5 @@
# master --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh
index 4fbf7a120..45815f737 100755
--- a/t/t5525-fetch-tagopt.sh
+++ b/t/t5525-fetch-tagopt.sh
@@ -8,7 +8,8 @@ setup_clone () {
git clone --mirror . $1 &&
git remote add remote_$1 $1 &&
(cd $1 &&
- git tag tag_$1)
+ git tag tag_$1 &&
+ git branch branch_$1)
}
test_expect_success setup '
@@ -21,21 +22,33 @@ test_expect_success setup '
test_expect_success "fetch with tagopt=--no-tags does not get tag" '
git fetch remote_one &&
- test_must_fail git show-ref tag_one
+ test_must_fail git show-ref tag_one &&
+ git show-ref remote_one/branch_one
'
test_expect_success "fetch --tags with tagopt=--no-tags gets tag" '
+ (
+ cd one &&
+ git branch second_branch_one
+ ) &&
git fetch --tags remote_one &&
- git show-ref tag_one
+ git show-ref tag_one &&
+ git show-ref remote_one/second_branch_one
'
test_expect_success "fetch --no-tags with tagopt=--tags does not get tag" '
git fetch --no-tags remote_two &&
- test_must_fail git show-ref tag_two
+ test_must_fail git show-ref tag_two &&
+ git show-ref remote_two/branch_two
'
test_expect_success "fetch with tagopt=--tags gets tag" '
+ (
+ cd two &&
+ git branch second_branch_two
+ ) &&
git fetch remote_two &&
- git show-ref tag_two
+ git show-ref tag_two &&
+ git show-ref remote_two/second_branch_two
'
test_done
diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh
new file mode 100755
index 000000000..6c5d3a4ce
--- /dev/null
+++ b/t/t5536-fetch-conflicts.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+test_description='fetch handles conflicting refspecs correctly'
+
+. ./test-lib.sh
+
+D=$(pwd)
+
+setup_repository () {
+ git init "$1" && (
+ cd "$1" &&
+ git config remote.origin.url "$D" &&
+ shift &&
+ for refspec in "$@"
+ do
+ git config --add remote.origin.fetch "$refspec"
+ done
+ )
+}
+
+verify_stderr () {
+ cat >expected &&
+ # We're not interested in the error
+ # "fatal: The remote end hung up unexpectedly":
+ grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
+ test_cmp expected actual
+}
+
+test_expect_success 'setup' '
+ git commit --allow-empty -m "Initial" &&
+ git branch branch1 &&
+ git tag tag1 &&
+ git commit --allow-empty -m "First" &&
+ git branch branch2 &&
+ git tag tag2
+'
+
+test_expect_success 'fetch with no conflict' '
+ setup_repository ok "+refs/heads/*:refs/remotes/origin/*" && (
+ cd ok &&
+ git fetch origin
+ )
+'
+
+test_expect_success 'fetch conflict: config vs. config' '
+ setup_repository ccc \
+ "+refs/heads/branch1:refs/remotes/origin/branch1" \
+ "+refs/heads/branch2:refs/remotes/origin/branch1" && (
+ cd ccc &&
+ test_must_fail git fetch origin 2>error &&
+ verify_stderr <<-\EOF
+ fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
+ EOF
+ )
+'
+
+test_expect_success 'fetch duplicate: config vs. config' '
+ setup_repository dcc \
+ "+refs/heads/*:refs/remotes/origin/*" \
+ "+refs/heads/branch1:refs/remotes/origin/branch1" && (
+ cd dcc &&
+ git fetch origin
+ )
+'
+
+test_expect_success 'fetch conflict: arg overrides config' '
+ setup_repository aoc \
+ "+refs/heads/*:refs/remotes/origin/*" && (
+ cd aoc &&
+ git fetch origin refs/heads/branch2:refs/remotes/origin/branch1
+ )
+'
+
+test_expect_success 'fetch conflict: arg vs. arg' '
+ setup_repository caa && (
+ cd caa &&
+ test_must_fail git fetch origin \
+ refs/heads/*:refs/remotes/origin/* \
+ refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
+ verify_stderr <<-\EOF
+ fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
+ EOF
+ )
+'
+
+test_expect_success 'fetch conflict: criss-cross args' '
+ setup_repository xaa \
+ "+refs/heads/*:refs/remotes/origin/*" && (
+ cd xaa &&
+ git fetch origin \
+ refs/heads/branch1:refs/remotes/origin/branch2 \
+ refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
+ verify_stderr <<-\EOF
+ warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2
+ warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1
+ EOF
+ )
+'
+
+test_done
diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh
index 1cd649e24..a953f1b55 100755
--- a/t/t6031-merge-recursive.sh
+++ b/t/t6031-merge-recursive.sh
@@ -2,7 +2,6 @@
test_description='merge-recursive: handle file mode'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success 'mode change in one branch: keep changed version' '
: >file1 &&
diff --git a/t/t9150/make-svk-dump b/t/t9150/make-svk-dump
index 2242f14eb..2242f14eb 100644..100755
--- a/t/t9150/make-svk-dump
+++ b/t/t9150/make-svk-dump
diff --git a/t/t9151/make-svnmerge-dump b/t/t9151/make-svnmerge-dump
index e1e138cb1..e1e138cb1 100644..100755
--- a/t/t9151/make-svnmerge-dump
+++ b/t/t9151/make-svnmerge-dump
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 3fb336890..812c9cd46 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -5,7 +5,6 @@
test_description='Test export of commits to CVS'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
if ! test_have_prereq PERL; then
skip_all='skipping git cvsexportcommit tests, perl not available'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 2f79146e6..aeae3ca76 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Library of functions shared by all tests scripts, included by
+# test-lib.sh.
#
# Copyright (c) 2005 Junio C Hamano
#
diff --git a/t/test-lib.sh b/t/test-lib.sh
index d303e6c94..1cf78d5b1 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Test framework for git. See t/README for usage.
#
# Copyright (c) 2005 Junio C Hamano
#
@@ -577,11 +577,9 @@ then
make_valgrind_symlink () {
# handle only executables, unless they are shell libraries that
- # need to be in the exec-path. We will just use "#!" as a
- # guess for a shell-script, since we have no idea what the user
- # may have configured as the shell path.
+ # need to be in the exec-path.
test -x "$1" ||
- test "#!" = "$(head -c 2 <"$1")" ||
+ test "# " = "$(head -c 2 <"$1")" ||
return;
base=$(basename "$1")
@@ -834,6 +832,10 @@ test_lazy_prereq SYMLINKS '
ln -s x y && test -h y
'
+test_lazy_prereq FILEMODE '
+ test "$(git config --bool core.filemode)" = true
+'
+
test_lazy_prereq CASE_INSENSITIVE_FS '
echo good >CamelCase &&
echo bad >camelcase &&