mirror of
https://github.com/git/git.git
synced 2026-01-18 06:34:21 +00:00
Merge branch 'gl/web' into next
* gl/web: (30 commits)
gitweb: git_annotate didn't expect negative numeric timezone
git-svn: add the 'dcommit' command
git-svn: recommend rebase for syncing against an SVN repo
git-svn: establish new connections on commit after fork
describe: fix off-by-one error in --abbrev=40 handling
gitweb: Remove creating directory for temporary files
gitweb: Remove git_diff_print subroutine
gitweb: git_blobdiff_plain is git_blobdiff('plain')
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
gitweb: Change here-doc back for style consistency in git_blobdiff
gitweb: Always display link to blobdiff_plain in git_blobdiff
gitweb: Add invisible hyperlink to from-file/to-file diff header
gitweb: Parse two-line from-file/to-file diff header in git_patchset_body
gitweb: Allow for pre-parsed difftree info in git_patchset_body
gitweb: Add support for hash_parent_base parameter for blobdiffs
gitweb: Use git_get_name_rev_tags for commitdiff_plain X-Git-Tag: header
gitweb: Add git_get_rev_name_tags function
gitweb: Faster return from git_get_preceding_references if possible
gitweb: Add git_get_{following,preceding}_references functions
gitweb: Streamify patch output in git_commitdiff
...
This commit is contained in:
@@ -10,10 +10,10 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply]
|
||||
[--no-add] [--index-info] [--allow-binary-replacement]
|
||||
[--reverse] [--reject] [-z] [-pNUM]
|
||||
[-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>]
|
||||
[<patch>...]
|
||||
[--no-add] [--index-info] [--allow-binary-replacement | --binary]
|
||||
[-R | --reverse] [--reject] [-z] [-pNUM] [-CNUM] [--inaccurate-eof]
|
||||
[--whitespace=<nowarn|warn|error|error-all|strip>] [--exclude=PATH]
|
||||
[--cached] [--verbose] [<patch>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -56,6 +56,11 @@ OPTIONS
|
||||
up-to-date, it is flagged as an error. This flag also
|
||||
causes the index file to be updated.
|
||||
|
||||
--cached::
|
||||
Apply a patch without touching the working tree. Instead, take the
|
||||
cached data, apply the patch, and store the result in the index,
|
||||
without using the working tree. This implies '--index'.
|
||||
|
||||
--index-info::
|
||||
Newer git-diff output has embedded 'index information'
|
||||
for each blob to help identify the original version that
|
||||
@@ -63,14 +68,14 @@ OPTIONS
|
||||
the original version of the blob is available locally,
|
||||
outputs information about them to the standard output.
|
||||
|
||||
--reverse::
|
||||
-R, --reverse::
|
||||
Apply the patch in reverse.
|
||||
|
||||
--reject::
|
||||
For atomicity, `git apply` fails the whole patch and
|
||||
For atomicity, gitlink:git-apply[1] by default fails the whole patch and
|
||||
does not touch the working tree when some of the hunks
|
||||
do not apply by default. This option makes it apply
|
||||
parts of the patch that are applicable, and send the
|
||||
do not apply. This option makes it apply
|
||||
the parts of the patch that are applicable, and send the
|
||||
rejected hunks to the standard output of the command.
|
||||
|
||||
-z::
|
||||
@@ -91,8 +96,8 @@ OPTIONS
|
||||
ever ignored.
|
||||
|
||||
--apply::
|
||||
If you use any of the options marked ``Turns off
|
||||
"apply"'' above, git-apply reads and outputs the
|
||||
If you use any of the options marked "Turns off
|
||||
'apply'" above, gitlink:git-apply[1] reads and outputs the
|
||||
information you asked without actually applying the
|
||||
patch. Give this flag after those flags to also apply
|
||||
the patch.
|
||||
@@ -104,7 +109,7 @@ OPTIONS
|
||||
the result with this option, which would apply the
|
||||
deletion part but not addition part.
|
||||
|
||||
--allow-binary-replacement::
|
||||
--allow-binary-replacement, --binary::
|
||||
When applying a patch, which is a git-enhanced patch
|
||||
that was prepared to record the pre- and post-image object
|
||||
name in full, and the path being patched exactly matches
|
||||
@@ -115,13 +120,18 @@ OPTIONS
|
||||
result. This allows binary files to be patched in a
|
||||
very limited way.
|
||||
|
||||
--exclude=<path-pattern>::
|
||||
Don't apply changes to files matching the given path pattern. This can
|
||||
be useful when importing patchsets, where you want to exclude certain
|
||||
files or directories.
|
||||
|
||||
--whitespace=<option>::
|
||||
When applying a patch, detect a new or modified line
|
||||
that ends with trailing whitespaces (this includes a
|
||||
line that solely consists of whitespaces). By default,
|
||||
the command outputs warning messages and applies the
|
||||
patch.
|
||||
When `git-apply` is used for statistics and not applying a
|
||||
When gitlink:git-apply[1] is used for statistics and not applying a
|
||||
patch, it defaults to `nowarn`.
|
||||
You can use different `<option>` to control this
|
||||
behavior:
|
||||
@@ -135,6 +145,17 @@ OPTIONS
|
||||
* `strip` outputs warnings for a few such errors, strips out the
|
||||
trailing whitespaces and applies the patch.
|
||||
|
||||
--inacurate-eof::
|
||||
Under certain circumstances, some versions of diff do not correctly
|
||||
detect a missing new-line at the end of the file. As a result, patches
|
||||
created by such diff programs do not record incomplete lines
|
||||
correctly. This option adds support for applying such patches by
|
||||
working around this bug.
|
||||
|
||||
--verbose::
|
||||
Report progress to stderr. By default, only a message about the
|
||||
current patch being applied will be printed. This option will cause
|
||||
additional information to be reported.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
@@ -3,21 +3,38 @@ git-blame(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-blame - Blame file lines on commits
|
||||
git-blame - Show what revision and author last modified each line of a file
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
git-blame file [options] file [revision]
|
||||
'git-blame' [-c] [-l] [-t] [-S <revs-file>] [--] <file> [<rev>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Annotates each line in the given file with information from the commit
|
||||
which introduced the line. Start annotation from the given revision.
|
||||
|
||||
Annotates each line in the given file with information from the revision which
|
||||
last modified the line. Optionally, start annotating from the given revision.
|
||||
|
||||
This report doesn't tell you anything about lines which have been deleted or
|
||||
replaced; you need to use a tool such as gitlink:git-diff[1] or the "pickaxe"
|
||||
interface briefly mentioned in the following paragraph.
|
||||
|
||||
Apart from supporting file annotation, git also supports searching the
|
||||
development history for when a code snippet occured in a change. This makes it
|
||||
possible to track when a code snippet was added to a file, moved or copied
|
||||
between files, and eventually deleted or replaced. It works by searching for
|
||||
a text string in the diff. A small example:
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
$ git log --pretty=oneline -S'blame_usage'
|
||||
5040f17eba15504bad66b14a645bddd9b015ebb7 blame -S <ancestry-file>
|
||||
ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-c, --compatibility::
|
||||
Use the same output mode as git-annotate (Default: off).
|
||||
Use the same output mode as gitlink:git-annotate[1] (Default: off).
|
||||
|
||||
-l, --long::
|
||||
Show long rev (Default: off).
|
||||
@@ -26,7 +43,7 @@ OPTIONS
|
||||
Show raw timestamp (Default: off).
|
||||
|
||||
-S, --rev-file <revs-file>::
|
||||
Use revs from revs-file instead of calling git-rev-list.
|
||||
Use revs from revs-file instead of calling gitlink:git-rev-list[1].
|
||||
|
||||
-h, --help::
|
||||
Show help message.
|
||||
|
||||
@@ -3,16 +3,19 @@ git-ls-remote(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-ls-remote - Look at references other repository has
|
||||
git-ls-remote - List references in a remote repository
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-ls-remote' [--heads] [--tags] <repository> <refs>...
|
||||
[verse]
|
||||
'git-ls-remote' [--heads] [--tags] [-u <exec> | --upload-pack <exec>]
|
||||
<repository> <refs>...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Displays the references other repository has.
|
||||
Displays references available in a remote repository along with the associated
|
||||
commit IDs.
|
||||
|
||||
|
||||
OPTIONS
|
||||
@@ -23,9 +26,16 @@ OPTIONS
|
||||
both, references stored in refs/heads and refs/tags are
|
||||
displayed.
|
||||
|
||||
-u <exec>, --upload-pack=<exec>::
|
||||
Specify the full path of gitlink:git-upload-pack[1] on the remote
|
||||
host. This allows listing references from repositories accessed via
|
||||
SSH and where the SSH deamon does not use the PATH configured by the
|
||||
user. Also see the '--exec' option for gitlink:git-peek-remote[1].
|
||||
|
||||
<repository>::
|
||||
Location of the repository. The shorthand defined in
|
||||
$GIT_DIR/branches/ can be used.
|
||||
$GIT_DIR/branches/ can be used. Use "." (dot) to list references in
|
||||
the local repository.
|
||||
|
||||
<refs>...::
|
||||
When unspecified, all references, after filtering done
|
||||
|
||||
@@ -12,10 +12,8 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
git-svn is a simple conduit for changesets between a single Subversion
|
||||
branch and git.
|
||||
|
||||
git-svn is not to be confused with git-svnimport. The were designed
|
||||
with very different goals in mind.
|
||||
branch and git. It is not to be confused with gitlink:git-svnimport[1].
|
||||
They were designed with very different goals in mind.
|
||||
|
||||
git-svn is designed for an individual developer who wants a
|
||||
bidirectional flow of changesets between a single branch in Subversion
|
||||
@@ -34,26 +32,38 @@ git-svnimport is designed for.
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
init::
|
||||
--
|
||||
|
||||
'init'::
|
||||
Creates an empty git repository with additional metadata
|
||||
directories for git-svn. The Subversion URL must be specified
|
||||
as a command-line argument.
|
||||
|
||||
fetch::
|
||||
Fetch unfetched revisions from the Subversion URL we are
|
||||
tracking. refs/remotes/git-svn will be updated to the
|
||||
latest revision.
|
||||
'fetch'::
|
||||
|
||||
Note: You should never attempt to modify the remotes/git-svn
|
||||
branch outside of git-svn. Instead, create a branch from
|
||||
remotes/git-svn and work on that branch. Use the 'commit'
|
||||
command (see below) to write git commits back to
|
||||
remotes/git-svn.
|
||||
Fetch unfetched revisions from the Subversion URL we are
|
||||
tracking. refs/remotes/git-svn will be updated to the
|
||||
latest revision.
|
||||
|
||||
See 'Additional Fetch Arguments' if you are interested in
|
||||
manually joining branches on commit.
|
||||
Note: You should never attempt to modify the remotes/git-svn
|
||||
branch outside of git-svn. Instead, create a branch from
|
||||
remotes/git-svn and work on that branch. Use the 'commit'
|
||||
command (see below) to write git commits back to
|
||||
remotes/git-svn.
|
||||
|
||||
commit::
|
||||
See '<<fetch-args,Additional Fetch Arguments>>' if you are interested in
|
||||
manually joining branches on commit.
|
||||
|
||||
'dcommit'::
|
||||
Commit all diffs from the current HEAD directly to the SVN
|
||||
repository, and then rebase or reset (depending on whether or
|
||||
not there is a diff between SVN and HEAD). It is recommended
|
||||
that you run git-svn fetch and rebase (not pull) your commits
|
||||
against the latest changes in the SVN repository.
|
||||
This is advantageous over 'commit' (below) because it produces
|
||||
cleaner, more linear history.
|
||||
|
||||
'commit'::
|
||||
Commit specified commit or tree objects to SVN. This relies on
|
||||
your imported fetch data being up-to-date. This makes
|
||||
absolutely no attempts to do patching when committing to SVN, it
|
||||
@@ -61,9 +71,9 @@ commit::
|
||||
commit. All merging is assumed to have taken place
|
||||
independently of git-svn functions.
|
||||
|
||||
rebuild::
|
||||
'rebuild'::
|
||||
Not a part of daily usage, but this is a useful command if
|
||||
you've just cloned a repository (using git-clone) that was
|
||||
you've just cloned a repository (using gitlink:git-clone[1]) that was
|
||||
tracked with git-svn. Unfortunately, git-clone does not clone
|
||||
git-svn metadata and the svn working tree that git-svn uses for
|
||||
its operations. This rebuilds the metadata so git-svn can
|
||||
@@ -71,130 +81,170 @@ rebuild::
|
||||
specified at the command-line if the directory/repository you're
|
||||
tracking has moved or changed protocols.
|
||||
|
||||
show-ignore::
|
||||
'show-ignore'::
|
||||
Recursively finds and lists the svn:ignore property on
|
||||
directories. The output is suitable for appending to
|
||||
the $GIT_DIR/info/exclude file.
|
||||
|
||||
--
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--
|
||||
|
||||
-r <ARG>::
|
||||
--revision <ARG>::
|
||||
Only used with the 'fetch' command.
|
||||
|
||||
Takes any valid -r<argument> svn would accept and passes it
|
||||
directly to svn. -r<ARG1>:<ARG2> ranges and "{" DATE "}" syntax
|
||||
is also supported. This is passed directly to svn, see svn
|
||||
documentation for more details.
|
||||
Only used with the 'fetch' command.
|
||||
|
||||
This can allow you to make partial mirrors when running fetch.
|
||||
Takes any valid -r<argument> svn would accept and passes it
|
||||
directly to svn. -r<ARG1>:<ARG2> ranges and "{" DATE "}" syntax
|
||||
is also supported. This is passed directly to svn, see svn
|
||||
documentation for more details.
|
||||
|
||||
This can allow you to make partial mirrors when running fetch.
|
||||
|
||||
-::
|
||||
--stdin::
|
||||
Only used with the 'commit' command.
|
||||
|
||||
Read a list of commits from stdin and commit them in reverse
|
||||
order. Only the leading sha1 is read from each line, so
|
||||
git-rev-list --pretty=oneline output can be used.
|
||||
Only used with the 'commit' command.
|
||||
|
||||
Read a list of commits from stdin and commit them in reverse
|
||||
order. Only the leading sha1 is read from each line, so
|
||||
git-rev-list --pretty=oneline output can be used.
|
||||
|
||||
--rmdir::
|
||||
Only used with the 'commit' command.
|
||||
|
||||
Remove directories from the SVN tree if there are no files left
|
||||
behind. SVN can version empty directories, and they are not
|
||||
removed by default if there are no files left in them. git
|
||||
cannot version empty directories. Enabling this flag will make
|
||||
the commit to SVN act like git.
|
||||
Only used with the 'commit' command.
|
||||
|
||||
repo-config key: svn.rmdir
|
||||
Remove directories from the SVN tree if there are no files left
|
||||
behind. SVN can version empty directories, and they are not
|
||||
removed by default if there are no files left in them. git
|
||||
cannot version empty directories. Enabling this flag will make
|
||||
the commit to SVN act like git.
|
||||
|
||||
repo-config key: svn.rmdir
|
||||
|
||||
-e::
|
||||
--edit::
|
||||
Only used with the 'commit' command.
|
||||
|
||||
Edit the commit message before committing to SVN. This is off by
|
||||
default for objects that are commits, and forced on when committing
|
||||
tree objects.
|
||||
Only used with the 'commit' command.
|
||||
|
||||
repo-config key: svn.edit
|
||||
Edit the commit message before committing to SVN. This is off by
|
||||
default for objects that are commits, and forced on when committing
|
||||
tree objects.
|
||||
|
||||
repo-config key: svn.edit
|
||||
|
||||
-l<num>::
|
||||
--find-copies-harder::
|
||||
Both of these are only used with the 'commit' command.
|
||||
|
||||
They are both passed directly to git-diff-tree see
|
||||
git-diff-tree(1) for more information.
|
||||
Both of these are only used with the 'commit' command.
|
||||
|
||||
repo-config key: svn.l
|
||||
repo-config key: svn.findcopiesharder
|
||||
They are both passed directly to git-diff-tree see
|
||||
gitlink:git-diff-tree[1] for more information.
|
||||
|
||||
[verse]
|
||||
repo-config key: svn.l
|
||||
repo-config key: svn.findcopiesharder
|
||||
|
||||
-A<filename>::
|
||||
--authors-file=<filename>::
|
||||
|
||||
Syntax is compatible with the files used by git-svnimport and
|
||||
git-cvsimport:
|
||||
Syntax is compatible with the files used by git-svnimport and
|
||||
git-cvsimport:
|
||||
|
||||
------------------------------------------------------------------------
|
||||
loginname = Joe User <user@example.com>
|
||||
loginname = Joe User <user@example.com>
|
||||
------------------------------------------------------------------------
|
||||
|
||||
If this option is specified and git-svn encounters an SVN
|
||||
committer name that does not exist in the authors-file, git-svn
|
||||
will abort operation. The user will then have to add the
|
||||
appropriate entry. Re-running the previous git-svn command
|
||||
after the authors-file is modified should continue operation.
|
||||
If this option is specified and git-svn encounters an SVN
|
||||
committer name that does not exist in the authors-file, git-svn
|
||||
will abort operation. The user will then have to add the
|
||||
appropriate entry. Re-running the previous git-svn command
|
||||
after the authors-file is modified should continue operation.
|
||||
|
||||
repo-config key: svn.authors-file
|
||||
repo-config key: svn.authors-file
|
||||
|
||||
-m::
|
||||
--merge::
|
||||
-s<strategy>::
|
||||
--strategy=<strategy>::
|
||||
|
||||
These are only used with the 'dcommit' command.
|
||||
|
||||
Passed directly to git-rebase when using 'dcommit' if a
|
||||
'git-reset' cannot be used (see dcommit).
|
||||
|
||||
-n::
|
||||
--dry-run::
|
||||
|
||||
This is only used with the 'dcommit' command.
|
||||
|
||||
Print out the series of git arguments that would show
|
||||
which diffs would be committed to SVN.
|
||||
|
||||
--
|
||||
|
||||
ADVANCED OPTIONS
|
||||
----------------
|
||||
--
|
||||
|
||||
-b<refname>::
|
||||
--branch <refname>::
|
||||
Used with 'fetch' or 'commit'.
|
||||
Used with 'fetch' or 'commit'.
|
||||
|
||||
This can be used to join arbitrary git branches to remotes/git-svn
|
||||
on new commits where the tree object is equivalent.
|
||||
This can be used to join arbitrary git branches to remotes/git-svn
|
||||
on new commits where the tree object is equivalent.
|
||||
|
||||
When used with different GIT_SVN_ID values, tags and branches in
|
||||
SVN can be tracked this way, as can some merges where the heads
|
||||
end up having completely equivalent content. This can even be
|
||||
used to track branches across multiple SVN _repositories_.
|
||||
When used with different GIT_SVN_ID values, tags and branches in
|
||||
SVN can be tracked this way, as can some merges where the heads
|
||||
end up having completely equivalent content. This can even be
|
||||
used to track branches across multiple SVN _repositories_.
|
||||
|
||||
This option may be specified multiple times, once for each
|
||||
branch.
|
||||
This option may be specified multiple times, once for each
|
||||
branch.
|
||||
|
||||
repo-config key: svn.branch
|
||||
repo-config key: svn.branch
|
||||
|
||||
-i<GIT_SVN_ID>::
|
||||
--id <GIT_SVN_ID>::
|
||||
This sets GIT_SVN_ID (instead of using the environment). See
|
||||
the section on "Tracking Multiple Repositories or Branches" for
|
||||
more information on using GIT_SVN_ID.
|
||||
|
||||
This sets GIT_SVN_ID (instead of using the environment). See the
|
||||
section on
|
||||
'<<tracking-multiple-repos,Tracking Multiple Repositories or Branches>>'
|
||||
for more information on using GIT_SVN_ID.
|
||||
|
||||
--
|
||||
|
||||
COMPATIBILITY OPTIONS
|
||||
---------------------
|
||||
--upgrade::
|
||||
Only used with the 'rebuild' command.
|
||||
--
|
||||
|
||||
Run this if you used an old version of git-svn that used
|
||||
"git-svn-HEAD" instead of "remotes/git-svn" as the branch
|
||||
for tracking the remote.
|
||||
--upgrade::
|
||||
Only used with the 'rebuild' command.
|
||||
|
||||
Run this if you used an old version of git-svn that used
|
||||
"git-svn-HEAD" instead of "remotes/git-svn" as the branch
|
||||
for tracking the remote.
|
||||
|
||||
--no-ignore-externals::
|
||||
Only used with the 'fetch' and 'rebuild' command.
|
||||
Only used with the 'fetch' and 'rebuild' command.
|
||||
|
||||
By default, git-svn passes --ignore-externals to svn to avoid
|
||||
fetching svn:external trees into git. Pass this flag to enable
|
||||
externals tracking directly via git.
|
||||
By default, git-svn passes --ignore-externals to svn to avoid
|
||||
fetching svn:external trees into git. Pass this flag to enable
|
||||
externals tracking directly via git.
|
||||
|
||||
Versions of svn that do not support --ignore-externals are
|
||||
automatically detected and this flag will be automatically
|
||||
enabled for them.
|
||||
Versions of svn that do not support --ignore-externals are
|
||||
automatically detected and this flag will be automatically
|
||||
enabled for them.
|
||||
|
||||
Otherwise, do not enable this flag unless you know what you're
|
||||
doing.
|
||||
Otherwise, do not enable this flag unless you know what you're
|
||||
doing.
|
||||
|
||||
repo-config key: svn.noignoreexternals
|
||||
repo-config key: svn.noignoreexternals
|
||||
|
||||
--
|
||||
|
||||
Basic Examples
|
||||
~~~~~~~~~~~~~~
|
||||
@@ -212,12 +262,26 @@ Tracking and contributing to an Subversion managed-project:
|
||||
git-svn commit <tree-ish> [<tree-ish_2> ...]
|
||||
# Commit all the git commits from my-branch that don't exist in SVN:
|
||||
git-svn commit remotes/git-svn..my-branch
|
||||
# Something is committed to SVN, pull the latest into your branch:
|
||||
git-svn fetch && git pull . remotes/git-svn
|
||||
# Something is committed to SVN, rebase the latest into your branch:
|
||||
git-svn fetch && git rebase remotes/git-svn
|
||||
# Append svn:ignore settings to the default git exclude file:
|
||||
git-svn show-ignore >> .git/info/exclude
|
||||
------------------------------------------------------------------------
|
||||
|
||||
REBASE VS. PULL
|
||||
---------------
|
||||
|
||||
Originally, git-svn recommended that the remotes/git-svn branch be
|
||||
pulled from. This is because the author favored 'git-svn commit B'
|
||||
to commit a single head rather than the 'git-svn commit A..B' notation
|
||||
to commit multiple commits.
|
||||
|
||||
If you use 'git-svn commit A..B' to commit several diffs and you do not
|
||||
have the latest remotes/git-svn merged into my-branch, you should use
|
||||
'git rebase' to update your work branch instead of 'git pull'. 'pull'
|
||||
can cause non-linear history to be flattened when committing into SVN,
|
||||
which can lead to merge commits reversing previous commits in SVN.
|
||||
|
||||
DESIGN PHILOSOPHY
|
||||
-----------------
|
||||
Merge tracking in Subversion is lacking and doing branched development
|
||||
@@ -226,6 +290,7 @@ any automated merge/branch tracking on the Subversion side and leaves it
|
||||
entirely up to the user on the git side. It's simply not worth it to do
|
||||
a useful translation when the original signal is weak.
|
||||
|
||||
[[tracking-multiple-repos]]
|
||||
TRACKING MULTIPLE REPOSITORIES OR BRANCHES
|
||||
------------------------------------------
|
||||
This is for advanced users, most users should ignore this section.
|
||||
@@ -241,6 +306,7 @@ invocation. The interface branch will be remotes/$GIT_SVN_ID, instead of
|
||||
remotes/git-svn. Any remotes/$GIT_SVN_ID branch should never be modified
|
||||
by the user outside of git-svn commands.
|
||||
|
||||
[[fetch-args]]
|
||||
ADDITIONAL FETCH ARGUMENTS
|
||||
--------------------------
|
||||
This is for advanced users, most users should ignore this section.
|
||||
@@ -251,11 +317,15 @@ optionally be specified in the form of sha1 hex sums at the
|
||||
command-line. Unfetched SVN revisions may also be tied to particular
|
||||
git commits with the following syntax:
|
||||
|
||||
------------------------------------------------
|
||||
svn_revision_number=git_commit_sha1
|
||||
------------------------------------------------
|
||||
|
||||
This allows you to tie unfetched SVN revision 375 to your current HEAD::
|
||||
This allows you to tie unfetched SVN revision 375 to your current HEAD:
|
||||
|
||||
`git-svn fetch 375=$(git-rev-parse HEAD)`
|
||||
------------------------------------------------
|
||||
git-svn fetch 375=$(git-rev-parse HEAD)
|
||||
------------------------------------------------
|
||||
|
||||
Advanced Example: Tracking a Reorganized Repository
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -310,6 +380,10 @@ the possible corner cases (git doesn't do it, either). Renamed and
|
||||
copied files are fully supported if they're similar enough for git to
|
||||
detect them.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
gitlink:git-rebase[1]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Eric Wong <normalperson@yhbt.net>.
|
||||
|
||||
@@ -8,8 +8,9 @@ git - the stupid content tracker
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate]
|
||||
[--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]
|
||||
[--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -3,26 +3,52 @@ gitk(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
gitk - Some git command not yet documented.
|
||||
|
||||
gitk - git repository browser
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'gitk' [ --option ] <args>...
|
||||
'gitk' [<option>...] [<revs>] [--] [<path>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Does something not yet documented.
|
||||
Displays changes in a repository or a selected set of commits. This includes
|
||||
visualizing the commit graph, showing information related to each commit, and
|
||||
the files in the trees of each revision.
|
||||
|
||||
Historically, gitk was the first repository browser. It's written in tcl/tk
|
||||
and started off in a separate repository but was later merged into the main
|
||||
git repository.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--option::
|
||||
Some option not yet documented.
|
||||
To control which revisions to shown, the command takes options applicable to
|
||||
the gitlink:git-rev-list[1] command. This manual page describes only the most
|
||||
frequently used options.
|
||||
|
||||
<args>...::
|
||||
Some argument not yet documented.
|
||||
-n <number>, --max-count=<number>::
|
||||
|
||||
Limits the number of commits to show.
|
||||
|
||||
--since=<date>::
|
||||
|
||||
Show commits more recent than a specific date.
|
||||
|
||||
--until=<date>::
|
||||
|
||||
Show commits older than a specific date.
|
||||
|
||||
<revs>::
|
||||
|
||||
Limit the revisions to show. This can be either a single revision
|
||||
meaning show from the given revision and back, or it can be a range in
|
||||
the form "'<from>'..'<to>'" to show all revisions between '<from>' and
|
||||
back to '<to>'. Note, more advanced revision selection can be applied.
|
||||
|
||||
<path>::
|
||||
|
||||
Limit commits to the ones touching files in the given paths. Note, to
|
||||
avoid ambiguity wrt. revision names use "--" to separate the paths
|
||||
from any preceeding options.
|
||||
|
||||
Examples
|
||||
--------
|
||||
@@ -37,13 +63,27 @@ gitk --since="2 weeks ago" \-- gitk::
|
||||
The "--" is necessary to avoid confusion with the *branch* named
|
||||
'gitk'
|
||||
|
||||
See Also
|
||||
--------
|
||||
'qgit(1)'::
|
||||
A repository browser written in C++ using Qt.
|
||||
|
||||
'gitview(1)'::
|
||||
A repository browser written in Python using Gtk. It's based on
|
||||
'bzrk(1)' and distributed in the contrib area of the git repository.
|
||||
|
||||
'tig(1)'::
|
||||
A minimal repository browser and git tool output highlighter written
|
||||
in C using Ncurses.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Paul Mackerras <paulus@samba.org>
|
||||
Written by Paul Mackerras <paulus@samba.org>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||
Documentation by Junio C Hamano, Jonas Fonseca, and the git-list
|
||||
<git@vger.kernel.org>.
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -7,40 +7,50 @@ gitview - A GTK based repository browser for git
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'gitview' [options] [args]
|
||||
'gitview' [options] [args]
|
||||
|
||||
DESCRIPTION
|
||||
---------
|
||||
|
||||
Dependencies
|
||||
Dependencies:
|
||||
|
||||
* Python 2.4
|
||||
* PyGTK 2.8 or later
|
||||
* PyCairo 1.0 or later
|
||||
|
||||
OPTIONS
|
||||
------
|
||||
--without-diff
|
||||
If the user doesn't want to list the commit diffs in the main window. This may speed up the repository browsing.
|
||||
-------
|
||||
--without-diff::
|
||||
|
||||
<args>
|
||||
All the valid option for git-rev-list(1)
|
||||
Key Bindings:
|
||||
F4:
|
||||
To maximize the window
|
||||
F5:
|
||||
To reread references.
|
||||
F11:
|
||||
Full screen
|
||||
F12:
|
||||
Leave full screen
|
||||
If the user doesn't want to list the commit diffs in the main window.
|
||||
This may speed up the repository browsing.
|
||||
|
||||
<args>::
|
||||
|
||||
All the valid option for gitlink:git-rev-list[1].
|
||||
|
||||
Key Bindings
|
||||
------------
|
||||
F4::
|
||||
To maximize the window
|
||||
|
||||
F5::
|
||||
To reread references.
|
||||
|
||||
F11::
|
||||
Full screen
|
||||
|
||||
F12::
|
||||
Leave full screen
|
||||
|
||||
EXAMPLES
|
||||
------
|
||||
gitview v2.6.12.. include/scsi drivers/scsi
|
||||
Show as the changes since version v2.6.12 that changed any file in the include/scsi
|
||||
or drivers/scsi subdirectories
|
||||
--------
|
||||
|
||||
gitview --since=2.weeks.ago
|
||||
Show the changes during the last two weeks
|
||||
gitview v2.6.12.. include/scsi drivers/scsi::
|
||||
|
||||
Show as the changes since version v2.6.12 that changed any file in the
|
||||
include/scsi or drivers/scsi subdirectories
|
||||
|
||||
gitview --since=2.weeks.ago::
|
||||
|
||||
Show the changes during the last two weeks
|
||||
|
||||
@@ -42,7 +42,7 @@ static void add_to_known_names(const char *path,
|
||||
struct commit_name *name = xmalloc(sizeof(struct commit_name) + len);
|
||||
|
||||
name->commit = commit;
|
||||
name->prio = prio;
|
||||
name->prio = prio;
|
||||
memcpy(name->path, path, len);
|
||||
idx = names;
|
||||
if (idx >= allocs) {
|
||||
@@ -154,7 +154,7 @@ int main(int argc, char **argv)
|
||||
tags = 1;
|
||||
else if (!strncmp(arg, "--abbrev=", 9)) {
|
||||
abbrev = strtoul(arg + 9, NULL, 10);
|
||||
if (abbrev < MINIMUM_ABBREV || 40 <= abbrev)
|
||||
if (abbrev < MINIMUM_ABBREV || 40 < abbrev)
|
||||
abbrev = DEFAULT_ABBREV;
|
||||
}
|
||||
else
|
||||
|
||||
39
git-svn.perl
39
git-svn.perl
@@ -51,7 +51,8 @@ my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
|
||||
$_message, $_file, $_follow_parent, $_no_metadata,
|
||||
$_template, $_shared, $_no_default_regex, $_no_graft_copy,
|
||||
$_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
|
||||
$_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m);
|
||||
$_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
|
||||
$_merge, $_strategy, $_dry_run);
|
||||
my (@_branch_from, %tree_map, %users, %rusers, %equiv);
|
||||
my ($_svn_co_url_revs, $_svn_pg_peg_revs);
|
||||
my @repo_path_split_cache;
|
||||
@@ -118,6 +119,11 @@ my %cmd = (
|
||||
{ 'message|m=s' => \$_message,
|
||||
'file|F=s' => \$_file,
|
||||
%cmt_opts } ],
|
||||
dcommit => [ \&dcommit, 'Commit several diffs to merge with upstream',
|
||||
{ 'merge|m|M' => \$_merge,
|
||||
'strategy|s=s' => \$_strategy,
|
||||
'dry-run|n' => \$_dry_run,
|
||||
%cmt_opts } ],
|
||||
);
|
||||
|
||||
my $cmd;
|
||||
@@ -500,6 +506,8 @@ sub commit_lib {
|
||||
my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
|
||||
my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
|
||||
|
||||
my $repo;
|
||||
($repo, $SVN_PATH) = repo_path_split($SVN_URL);
|
||||
set_svn_commit_env();
|
||||
foreach my $c (@revs) {
|
||||
my $log_msg = get_commit_message($c, $commit_msg);
|
||||
@@ -508,6 +516,8 @@ sub commit_lib {
|
||||
# can't track down... (it's probably in the SVN code)
|
||||
defined(my $pid = open my $fh, '-|') or croak $!;
|
||||
if (!$pid) {
|
||||
$SVN_LOG = libsvn_connect($repo);
|
||||
$SVN = libsvn_connect($repo);
|
||||
my $ed = SVN::Git::Editor->new(
|
||||
{ r => $r_last,
|
||||
ra => $SVN,
|
||||
@@ -557,6 +567,33 @@ sub commit_lib {
|
||||
unlink $commit_msg;
|
||||
}
|
||||
|
||||
sub dcommit {
|
||||
my $gs = "refs/remotes/$GIT_SVN";
|
||||
chomp(my @refs = safe_qx(qw/git-rev-list --no-merges/, "$gs..HEAD"));
|
||||
foreach my $d (reverse @refs) {
|
||||
if ($_dry_run) {
|
||||
print "diff-tree $d~1 $d\n";
|
||||
} else {
|
||||
commit_diff("$d~1", $d);
|
||||
}
|
||||
}
|
||||
return if $_dry_run;
|
||||
fetch();
|
||||
my @diff = safe_qx(qw/git-diff-tree HEAD/, $gs);
|
||||
my @finish;
|
||||
if (@diff) {
|
||||
@finish = qw/rebase/;
|
||||
push @finish, qw/--merge/ if $_merge;
|
||||
push @finish, "--strategy=$_strategy" if $_strategy;
|
||||
print STDERR "W: HEAD and $gs differ, using @finish:\n", @diff;
|
||||
} else {
|
||||
print "No changes between current HEAD and $gs\n",
|
||||
"Hard resetting to the latest $gs\n";
|
||||
@finish = qw/reset --hard/;
|
||||
}
|
||||
sys('git', @finish, $gs);
|
||||
}
|
||||
|
||||
sub show_ignore {
|
||||
$SVN_URL ||= file_to_s("$GIT_SVN_DIR/info/url");
|
||||
$_use_lib ? show_ignore_lib() : show_ignore_cmd();
|
||||
|
||||
@@ -273,10 +273,22 @@ td.mode {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
div.diff a.list {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.diff a.list:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.diff.to_file a.list,
|
||||
div.diff.to_file,
|
||||
div.diff.add {
|
||||
color: #008800;
|
||||
}
|
||||
|
||||
div.diff.from_file a.list,
|
||||
div.diff.from_file,
|
||||
div.diff.rem {
|
||||
color: #cc0000;
|
||||
}
|
||||
@@ -285,6 +297,10 @@ div.diff.chunk_header {
|
||||
color: #990099;
|
||||
}
|
||||
|
||||
div.diff.incomplete {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
div.diff_info {
|
||||
font-family: monospace;
|
||||
color: #000099;
|
||||
|
||||
@@ -31,9 +31,6 @@ our $GIT = "++GIT_BINDIR++/git";
|
||||
#our $projectroot = "/pub/scm";
|
||||
our $projectroot = "++GITWEB_PROJECTROOT++";
|
||||
|
||||
# location for temporary files needed for diffs
|
||||
our $git_temp = "/tmp/gitweb";
|
||||
|
||||
# target of the home link on top of all pages
|
||||
our $home_link = $my_uri || "/";
|
||||
|
||||
@@ -144,9 +141,6 @@ require $GITWEB_CONFIG if -e $GITWEB_CONFIG;
|
||||
our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown";
|
||||
|
||||
$projects_list ||= $projectroot;
|
||||
if (! -d $git_temp) {
|
||||
mkdir($git_temp, 0700) || die_error(undef, "Couldn't mkdir $git_temp");
|
||||
}
|
||||
|
||||
# ======================================================================
|
||||
# input validation and dispatch
|
||||
@@ -211,6 +205,13 @@ if (defined $hash_base) {
|
||||
}
|
||||
}
|
||||
|
||||
our $hash_parent_base = $cgi->param('hpb');
|
||||
if (defined $hash_parent_base) {
|
||||
if (!validate_input($hash_parent_base)) {
|
||||
die_error(undef, "Invalid hash parent base parameter");
|
||||
}
|
||||
}
|
||||
|
||||
our $page = $cgi->param('pg');
|
||||
if (defined $page) {
|
||||
if ($page =~ m/[^0-9]$/) {
|
||||
@@ -270,13 +271,14 @@ sub href(%) {
|
||||
my %params = @_;
|
||||
|
||||
my @mapping = (
|
||||
action => "a",
|
||||
project => "p",
|
||||
action => "a",
|
||||
file_name => "f",
|
||||
file_parent => "fp",
|
||||
hash => "h",
|
||||
hash_parent => "hp",
|
||||
hash_base => "hb",
|
||||
hash_parent_base => "hpb",
|
||||
page => "pg",
|
||||
searchtext => "s",
|
||||
);
|
||||
@@ -446,7 +448,13 @@ sub mode_str {
|
||||
|
||||
# convert file mode in octal to file type string
|
||||
sub file_type {
|
||||
my $mode = oct shift;
|
||||
my $mode = shift;
|
||||
|
||||
if ($mode !~ m/^[0-7]+$/) {
|
||||
return $mode;
|
||||
} else {
|
||||
$mode = oct $mode;
|
||||
}
|
||||
|
||||
if (S_ISDIR($mode & S_IFMT)) {
|
||||
return "directory";
|
||||
@@ -524,6 +532,26 @@ sub format_subject_html {
|
||||
}
|
||||
}
|
||||
|
||||
sub format_diff_line {
|
||||
my $line = shift;
|
||||
my $char = substr($line, 0, 1);
|
||||
my $diff_class = "";
|
||||
|
||||
chomp $line;
|
||||
|
||||
if ($char eq '+') {
|
||||
$diff_class = " add";
|
||||
} elsif ($char eq "-") {
|
||||
$diff_class = " rem";
|
||||
} elsif ($char eq "@") {
|
||||
$diff_class = " chunk_header";
|
||||
} elsif ($char eq "\\") {
|
||||
$diff_class = " incomplete";
|
||||
}
|
||||
$line = untabify($line);
|
||||
return "<div class=\"diff$diff_class\">" . esc_html($line) . "</div>\n";
|
||||
}
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## git utility subroutines, invoking git commands
|
||||
|
||||
@@ -590,6 +618,26 @@ sub git_get_hash_by_path {
|
||||
return $3;
|
||||
}
|
||||
|
||||
# converts symbolic name to hash
|
||||
sub git_to_hash {
|
||||
my @params = @_;
|
||||
return undef unless @params;
|
||||
|
||||
open my $fd, "-|", $GIT, "rev-parse", @params
|
||||
or return undef;
|
||||
my @hashes = map { chomp; $_ } <$fd>;
|
||||
close $fd;
|
||||
|
||||
if (wantarray) {
|
||||
return @hashes;
|
||||
} elsif (scalar(@hashes) == 1) {
|
||||
# single hash
|
||||
return $hashes[0];
|
||||
} else {
|
||||
return \@hashes;
|
||||
}
|
||||
}
|
||||
|
||||
## ......................................................................
|
||||
## git utility functions, directly accessing git repository
|
||||
|
||||
@@ -729,6 +777,73 @@ sub git_get_references {
|
||||
return \%refs;
|
||||
}
|
||||
|
||||
sub git_get_following_references {
|
||||
my $hash = shift || return undef;
|
||||
my $type = shift;
|
||||
my $base = shift || $hash_base || "HEAD";
|
||||
|
||||
my $refs = git_get_references($type);
|
||||
open my $fd, "-|", $GIT, "rev-list", $base
|
||||
or return undef;
|
||||
my @commits = map { chomp; $_ } <$fd>;
|
||||
close $fd
|
||||
or return undef;
|
||||
|
||||
my @reflist;
|
||||
my $lastref;
|
||||
|
||||
foreach my $commit (@commits) {
|
||||
foreach my $ref (@{$refs->{$commit}}) {
|
||||
$lastref = $ref;
|
||||
push @reflist, $lastref;
|
||||
}
|
||||
if ($commit eq $hash) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return wantarray ? @reflist : $lastref;
|
||||
}
|
||||
|
||||
sub git_get_preceding_references {
|
||||
my $hash = shift || return undef;
|
||||
my $type = shift;
|
||||
|
||||
my $refs = git_get_references($type);
|
||||
open my $fd, "-|", $GIT, "rev-list", $hash
|
||||
or return undef;
|
||||
my @commits = map { chomp; $_ } <$fd>;
|
||||
close $fd
|
||||
or return undef;
|
||||
|
||||
my @reflist;
|
||||
|
||||
foreach my $commit (@commits) {
|
||||
foreach my $ref (@{$refs->{$commit}}) {
|
||||
return $ref unless wantarray;
|
||||
push @reflist, $ref;
|
||||
}
|
||||
}
|
||||
|
||||
return @reflist;
|
||||
}
|
||||
|
||||
sub git_get_rev_name_tags {
|
||||
my $hash = shift || return undef;
|
||||
|
||||
open my $fd, "-|", $GIT, "name-rev", "--tags", $hash
|
||||
or return;
|
||||
my $name_rev = <$fd>;
|
||||
close $fd;
|
||||
|
||||
if ($name_rev =~ m|^$hash tags/(.*)$|) {
|
||||
return $1;
|
||||
} else {
|
||||
# catches also '$hash undefined' output
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## parse to hash functions
|
||||
|
||||
@@ -1367,7 +1482,7 @@ sub git_print_simplified_log {
|
||||
## functions printing large fragments of HTML
|
||||
|
||||
sub git_difftree_body {
|
||||
my ($difftree, $parent) = @_;
|
||||
my ($difftree, $hash, $parent) = @_;
|
||||
|
||||
print "<div class=\"list_head\">\n";
|
||||
if ($#{$difftree} > 10) {
|
||||
@@ -1456,8 +1571,10 @@ sub git_difftree_body {
|
||||
}
|
||||
print "<td>";
|
||||
if ($diff{'to_id'} ne $diff{'from_id'}) { # modified
|
||||
print $cgi->a({-href => href(action=>"blobdiff", hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
|
||||
hash_base=>$hash, file_name=>$diff{'file'}),
|
||||
print $cgi->a({-href => href(action=>"blobdiff",
|
||||
hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
|
||||
hash_base=>$hash, hash_parent_base=>$parent,
|
||||
file_name=>$diff{'file'}),
|
||||
-class => "list"}, esc_html($diff{'file'}));
|
||||
} else { # only mode changed
|
||||
print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
|
||||
@@ -1472,8 +1589,10 @@ sub git_difftree_body {
|
||||
"blob");
|
||||
if ($diff{'to_id'} ne $diff{'from_id'}) { # modified
|
||||
print " | " .
|
||||
$cgi->a({-href => href(action=>"blobdiff", hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
|
||||
hash_base=>$hash, file_name=>$diff{'file'})},
|
||||
$cgi->a({-href => href(action=>"blobdiff",
|
||||
hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
|
||||
hash_base=>$hash, hash_parent_base=>$parent,
|
||||
file_name=>$diff{'file'})},
|
||||
"diff");
|
||||
}
|
||||
print " | " .
|
||||
@@ -1505,8 +1624,9 @@ sub git_difftree_body {
|
||||
"blob");
|
||||
if ($diff{'to_id'} ne $diff{'from_id'}) {
|
||||
print " | " .
|
||||
$cgi->a({-href => href(action=>"blobdiff", hash_base=>$hash,
|
||||
$cgi->a({-href => href(action=>"blobdiff",
|
||||
hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
|
||||
hash_base=>$hash, hash_parent_base=>$parent,
|
||||
file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})},
|
||||
"diff");
|
||||
}
|
||||
@@ -1518,6 +1638,131 @@ sub git_difftree_body {
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
sub git_patchset_body {
|
||||
my ($fd, $difftree, $hash, $hash_parent) = @_;
|
||||
|
||||
my $patch_idx = 0;
|
||||
my $in_header = 0;
|
||||
my $patch_found = 0;
|
||||
my $diffinfo;
|
||||
|
||||
print "<div class=\"patchset\">\n";
|
||||
|
||||
LINE:
|
||||
while (my $patch_line @$fd>) {
|
||||
chomp $patch_line;
|
||||
|
||||
if ($patch_line =~ m/^diff /) { # "git diff" header
|
||||
# beginning of patch (in patchset)
|
||||
if ($patch_found) {
|
||||
# close previous patch
|
||||
print "</div>\n"; # class="patch"
|
||||
} else {
|
||||
# first patch in patchset
|
||||
$patch_found = 1;
|
||||
}
|
||||
print "<div class=\"patch\">\n";
|
||||
|
||||
if (ref($difftree->[$patch_idx]) eq "HASH") {
|
||||
$diffinfo = $difftree->[$patch_idx];
|
||||
} else {
|
||||
$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);
|
||||
}
|
||||
$patch_idx++;
|
||||
|
||||
# for now, no extended header, hence we skip empty patches
|
||||
# companion to next LINE if $in_header;
|
||||
if ($diffinfo->{'from_id'} eq $diffinfo->{'to_id'}) { # no change
|
||||
$in_header = 1;
|
||||
next LINE;
|
||||
}
|
||||
|
||||
if ($diffinfo->{'status'} eq "A") { # added
|
||||
print "<div class=\"diff_info\">" . file_type($diffinfo->{'to_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},
|
||||
$diffinfo->{'to_id'}) . "(new)" .
|
||||
"</div>\n"; # class="diff_info"
|
||||
|
||||
} elsif ($diffinfo->{'status'} eq "D") { # deleted
|
||||
print "<div class=\"diff_info\">" . file_type($diffinfo->{'from_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},
|
||||
$diffinfo->{'from_id'}) . "(deleted)" .
|
||||
"</div>\n"; # class="diff_info"
|
||||
|
||||
} elsif ($diffinfo->{'status'} eq "R" || # renamed
|
||||
$diffinfo->{'status'} eq "C" || # copied
|
||||
$diffinfo->{'status'} eq "2") { # with two filenames (from git_blobdiff)
|
||||
print "<div class=\"diff_info\">" .
|
||||
file_type($diffinfo->{'from_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'from_file'})},
|
||||
$diffinfo->{'from_id'}) .
|
||||
" -> " .
|
||||
file_type($diffinfo->{'to_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'to_file'})},
|
||||
$diffinfo->{'to_id'});
|
||||
print "</div>\n"; # class="diff_info"
|
||||
|
||||
} else { # modified, mode changed, ...
|
||||
print "<div class=\"diff_info\">" .
|
||||
file_type($diffinfo->{'from_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},
|
||||
$diffinfo->{'from_id'}) .
|
||||
" -> " .
|
||||
file_type($diffinfo->{'to_mode'}) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},
|
||||
$diffinfo->{'to_id'});
|
||||
print "</div>\n"; # class="diff_info"
|
||||
}
|
||||
|
||||
#print "<div class=\"diff extended_header\">\n";
|
||||
$in_header = 1;
|
||||
next LINE;
|
||||
} # start of patch in patchset
|
||||
|
||||
|
||||
if ($in_header && $patch_line =~ m/^---/) {
|
||||
#print "</div>\n"; # class="diff extended_header"
|
||||
$in_header = 0;
|
||||
|
||||
my $file = $diffinfo->{'from_file'};
|
||||
$file ||= $diffinfo->{'file'};
|
||||
$file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$diffinfo->{'from_id'}, file_name=>$file),
|
||||
-class => "list"}, esc_html($file));
|
||||
$patch_line =~ s|a/.*$|a/$file|g;
|
||||
print "<div class=\"diff from_file\">$patch_line</div>\n";
|
||||
|
||||
$patch_line = <$fd>;
|
||||
chomp $patch_line;
|
||||
|
||||
#$patch_line =~ m/^+++/;
|
||||
$file = $diffinfo->{'to_file'};
|
||||
$file ||= $diffinfo->{'file'};
|
||||
$file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$diffinfo->{'to_id'}, file_name=>$file),
|
||||
-class => "list"}, esc_html($file));
|
||||
$patch_line =~ s|b/.*|b/$file|g;
|
||||
print "<div class=\"diff to_file\">$patch_line</div>\n";
|
||||
|
||||
next LINE;
|
||||
}
|
||||
next LINE if $in_header;
|
||||
|
||||
print format_diff_line($patch_line);
|
||||
}
|
||||
print "</div>\n" if $patch_found; # class="patch"
|
||||
|
||||
print "</div>\n"; # class="patchset"
|
||||
}
|
||||
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
sub git_shortlog_body {
|
||||
# uses global variable $project
|
||||
my ($revlist, $from, $to, $refs, $extra) = @_;
|
||||
@@ -1609,8 +1854,10 @@ sub git_history_body {
|
||||
if (defined $blob_current && defined $blob_parent &&
|
||||
$blob_current ne $blob_parent) {
|
||||
print " | " .
|
||||
$cgi->a({-href => href(action=>"blobdiff", hash=>$blob_current, hash_parent=>$blob_parent,
|
||||
hash_base=>$commit, file_name=>$file_name)},
|
||||
$cgi->a({-href => href(action=>"blobdiff",
|
||||
hash=>$blob_current, hash_parent=>$blob_parent,
|
||||
hash_base=>$hash_base, hash_parent_base=>$commit,
|
||||
file_name=>$file_name)},
|
||||
"diff to current");
|
||||
}
|
||||
}
|
||||
@@ -1722,77 +1969,6 @@ sub git_heads_body {
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## functions printing large fragments, format as one of arguments
|
||||
|
||||
sub git_diff_print {
|
||||
my $from = shift;
|
||||
my $from_name = shift;
|
||||
my $to = shift;
|
||||
my $to_name = shift;
|
||||
my $format = shift || "html";
|
||||
|
||||
my $from_tmp = "/dev/null";
|
||||
my $to_tmp = "/dev/null";
|
||||
my $pid = $$;
|
||||
|
||||
# create tmp from-file
|
||||
if (defined $from) {
|
||||
$from_tmp = "$git_temp/gitweb_" . $$ . "_from";
|
||||
open my $fd2, "> $from_tmp";
|
||||
open my $fd, "-|", $GIT, "cat-file", "blob", $from;
|
||||
my @file = <$fd>;
|
||||
print $fd2 @file;
|
||||
close $fd2;
|
||||
close $fd;
|
||||
}
|
||||
|
||||
# create tmp to-file
|
||||
if (defined $to) {
|
||||
$to_tmp = "$git_temp/gitweb_" . $$ . "_to";
|
||||
open my $fd2, "> $to_tmp";
|
||||
open my $fd, "-|", $GIT, "cat-file", "blob", $to;
|
||||
my @file = <$fd>;
|
||||
print $fd2 @file;
|
||||
close $fd2;
|
||||
close $fd;
|
||||
}
|
||||
|
||||
open my $fd, "-|", "/usr/bin/diff -u -p -L \'$from_name\' -L \'$to_name\' $from_tmp $to_tmp";
|
||||
if ($format eq "plain") {
|
||||
undef $/;
|
||||
print <$fd>;
|
||||
$/ = "\n";
|
||||
} else {
|
||||
while (my $line = <$fd>) {
|
||||
chomp $line;
|
||||
my $char = substr($line, 0, 1);
|
||||
my $diff_class = "";
|
||||
if ($char eq '+') {
|
||||
$diff_class = " add";
|
||||
} elsif ($char eq "-") {
|
||||
$diff_class = " rem";
|
||||
} elsif ($char eq "@") {
|
||||
$diff_class = " chunk_header";
|
||||
} elsif ($char eq "\\") {
|
||||
# skip errors
|
||||
next;
|
||||
}
|
||||
$line = untabify($line);
|
||||
print "<div class=\"diff$diff_class\">" . esc_html($line) . "</div>\n";
|
||||
}
|
||||
}
|
||||
close $fd;
|
||||
|
||||
if (defined $from) {
|
||||
unlink($from_tmp);
|
||||
}
|
||||
if (defined $to) {
|
||||
unlink($to_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## ======================================================================
|
||||
## ======================================================================
|
||||
## actions
|
||||
@@ -2115,7 +2291,7 @@ HTML
|
||||
chomp $line;
|
||||
$line_class_num = ($line_class_num + 1) % $line_class_len;
|
||||
|
||||
if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) \+\d\d\d\d\t(\d+)\)(.*)$/) {
|
||||
if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) [+-]\d\d\d\d\t(\d+)\)(.*)$/) {
|
||||
$long_rev = $1;
|
||||
$author = $2;
|
||||
$time = $3;
|
||||
@@ -2556,51 +2732,182 @@ sub git_commit {
|
||||
git_print_log($co{'comment'});
|
||||
print "</div>\n";
|
||||
|
||||
git_difftree_body(\@difftree, $parent);
|
||||
git_difftree_body(\@difftree, $hash, $parent);
|
||||
|
||||
git_footer_html();
|
||||
}
|
||||
|
||||
sub git_blobdiff {
|
||||
mkdir($git_temp, 0700);
|
||||
git_header_html();
|
||||
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
|
||||
my $format = shift || 'html';
|
||||
|
||||
my $fd;
|
||||
my @difftree;
|
||||
my %diffinfo;
|
||||
my $expires;
|
||||
|
||||
# preparing $fd and %diffinfo for git_patchset_body
|
||||
# new style URI
|
||||
if (defined $hash_base && defined $hash_parent_base) {
|
||||
if (defined $file_name) {
|
||||
# read raw output
|
||||
open $fd, "-|", $GIT, "diff-tree", '-r', '-M', '-C', $hash_parent_base, $hash_base,
|
||||
"--", $file_name
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
@difftree = map { chomp; $_ } <$fd>;
|
||||
close $fd
|
||||
or die_error(undef, "Reading git-diff-tree failed");
|
||||
@difftree
|
||||
or die_error('404 Not Found', "Blob diff not found");
|
||||
|
||||
} elsif (defined $hash) { # try to find filename from $hash
|
||||
if ($hash !~ /[0-9a-fA-F]{40}/) {
|
||||
$hash = git_to_hash($hash);
|
||||
}
|
||||
|
||||
# read filtered raw output
|
||||
open $fd, "-|", $GIT, "diff-tree", '-r', '-M', '-C', $hash_parent_base, $hash_base
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
@difftree =
|
||||
# ':100644 100644 03b21826... 3b93d5e7... M ls-files.c'
|
||||
# $hash == to_id
|
||||
grep { /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash/ }
|
||||
map { chomp; $_ } <$fd>;
|
||||
close $fd
|
||||
or die_error(undef, "Reading git-diff-tree failed");
|
||||
@difftree
|
||||
or die_error('404 Not Found', "Blob diff not found");
|
||||
|
||||
} else {
|
||||
die_error('404 Not Found', "Missing one of the blob diff parameters");
|
||||
}
|
||||
|
||||
if (@difftree > 1) {
|
||||
die_error('404 Not Found', "Ambiguous blob diff specification");
|
||||
}
|
||||
|
||||
%diffinfo = parse_difftree_raw_line($difftree[0]);
|
||||
$file_parent ||= $diffinfo{'from_file'} || $file_name || $diffinfo{'file'};
|
||||
$file_name ||= $diffinfo{'to_file'} || $diffinfo{'file'};
|
||||
|
||||
$hash_parent ||= $diffinfo{'from_id'};
|
||||
$hash ||= $diffinfo{'to_id'};
|
||||
|
||||
# non-textual hash id's can be cached
|
||||
if ($hash_base =~ m/^[0-9a-fA-F]{40}$/ &&
|
||||
$hash_parent_base =~ m/^[0-9a-fA-F]{40}$/) {
|
||||
$expires = '+1d';
|
||||
}
|
||||
|
||||
# open patch output
|
||||
open $fd, "-|", $GIT, "diff-tree", '-r', '-p', '-M', '-C', $hash_parent_base, $hash_base,
|
||||
"--", $file_name
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
}
|
||||
|
||||
# old/legacy style URI
|
||||
if (!%diffinfo && # if new style URI failed
|
||||
defined $hash && defined $hash_parent) {
|
||||
# fake git-diff-tree raw output
|
||||
$diffinfo{'from_mode'} = $diffinfo{'to_mode'} = "blob";
|
||||
$diffinfo{'from_id'} = $hash_parent;
|
||||
$diffinfo{'to_id'} = $hash;
|
||||
if (defined $file_name) {
|
||||
if (defined $file_parent) {
|
||||
$diffinfo{'status'} = '2';
|
||||
$diffinfo{'from_file'} = $file_parent;
|
||||
$diffinfo{'to_file'} = $file_name;
|
||||
} else { # assume not renamed
|
||||
$diffinfo{'status'} = '1';
|
||||
$diffinfo{'from_file'} = $file_name;
|
||||
$diffinfo{'to_file'} = $file_name;
|
||||
}
|
||||
} else { # no filename given
|
||||
$diffinfo{'status'} = '2';
|
||||
$diffinfo{'from_file'} = $hash_parent;
|
||||
$diffinfo{'to_file'} = $hash;
|
||||
}
|
||||
|
||||
# non-textual hash id's can be cached
|
||||
if ($hash =~ m/^[0-9a-fA-F]{40}$/ &&
|
||||
$hash_parent =~ m/^[0-9a-fA-F]{40}$/) {
|
||||
$expires = '+1d';
|
||||
}
|
||||
|
||||
# open patch output
|
||||
#open $fd, "-|", $GIT, "diff", '-p', $hash_parent, $hash
|
||||
open $fd, "-|", $GIT, "diff", '-p', $hash, $hash_parent
|
||||
or die_error(undef, "Open git-diff failed");
|
||||
} else {
|
||||
die_error('404 Not Found', "Missing one of the blob diff parameters")
|
||||
unless %diffinfo;
|
||||
}
|
||||
|
||||
# header
|
||||
if ($format eq 'html') {
|
||||
my $formats_nav =
|
||||
$cgi->a({-href => href(action=>"blobdiff_plain",
|
||||
hash=>$hash, hash_parent=>$hash_parent)},
|
||||
hash=>$hash, hash_parent=>$hash_parent,
|
||||
hash_base=>$hash_base, hash_parent_base=>$hash_parent_base,
|
||||
file_name=>$file_name, file_parent=>$file_parent)},
|
||||
"plain");
|
||||
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
|
||||
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
|
||||
git_header_html(undef, $expires);
|
||||
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
|
||||
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
|
||||
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
|
||||
} else {
|
||||
print "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n";
|
||||
print "<div class=\"title\">$hash vs $hash_parent</div>\n";
|
||||
}
|
||||
if (defined $file_name) {
|
||||
git_print_page_path($file_name, "blob", $hash_base);
|
||||
} else {
|
||||
print "<div class=\"page_path\"></div>\n";
|
||||
}
|
||||
|
||||
} elsif ($format eq 'plain') {
|
||||
print $cgi->header(
|
||||
-type => 'text/plain',
|
||||
-charset => 'utf-8',
|
||||
-expires => $expires,
|
||||
-content_disposition => qq(inline; filename="${file_name}.patch"));
|
||||
|
||||
print "X-Git-Url: " . $cgi->self_url() . "\n\n";
|
||||
|
||||
} else {
|
||||
print <<HTML;
|
||||
<div class="page_nav"><br/><br/></div>
|
||||
<div class="title">$hash vs $hash_parent</div>
|
||||
HTML
|
||||
die_error(undef, "Unknown blobdiff format");
|
||||
}
|
||||
|
||||
# patch
|
||||
if ($format eq 'html') {
|
||||
print "<div class=\"page_body\">\n";
|
||||
|
||||
git_patchset_body($fd, [ \%diffinfo ], $hash_base, $hash_parent_base);
|
||||
close $fd;
|
||||
|
||||
print "</div>\n"; # class="page_body"
|
||||
git_footer_html();
|
||||
|
||||
} else {
|
||||
while (my $line = <$fd>) {
|
||||
$line =~ s!a/($hash|$hash_parent)!a/$diffinfo{'from_file'}!g;
|
||||
$line =~ s!b/($hash|$hash_parent)!b/$diffinfo{'to_file'}!g;
|
||||
|
||||
print $line;
|
||||
|
||||
last if $line =~ m!^\+\+\+!;
|
||||
}
|
||||
local $/ = undef;
|
||||
print <$fd>;
|
||||
close $fd;
|
||||
}
|
||||
git_print_page_path($file_name, "blob", $hash_base);
|
||||
print "<div class=\"page_body\">\n" .
|
||||
"<div class=\"diff_info\">blob:" .
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$hash_parent,
|
||||
hash_base=>$hash_base, file_name=>($file_parent || $file_name))},
|
||||
$hash_parent) .
|
||||
" -> blob:" .
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$hash,
|
||||
hash_base=>$hash_base, file_name=>$file_name)},
|
||||
$hash) .
|
||||
"</div>\n";
|
||||
git_diff_print($hash_parent, $file_name || $hash_parent, $hash, $file_name || $hash);
|
||||
print "</div>"; # page_body
|
||||
git_footer_html();
|
||||
}
|
||||
|
||||
sub git_blobdiff_plain {
|
||||
mkdir($git_temp, 0700);
|
||||
print $cgi->header(-type => "text/plain", -charset => 'utf-8');
|
||||
git_diff_print($hash_parent, $file_name || $hash_parent, $hash, $file_name || $hash, "plain");
|
||||
git_blobdiff('plain');
|
||||
}
|
||||
|
||||
sub git_commitdiff {
|
||||
mkdir($git_temp, 0700);
|
||||
my $format = shift || 'html';
|
||||
my %co = parse_commit($hash);
|
||||
if (!%co) {
|
||||
die_error(undef, "Unknown commit object");
|
||||
@@ -2608,143 +2915,99 @@ sub git_commitdiff {
|
||||
if (!defined $hash_parent) {
|
||||
$hash_parent = $co{'parent'} || '--root';
|
||||
}
|
||||
open my $fd, "-|", $GIT, "diff-tree", '-r', $hash_parent, $hash
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
my @difftree = map { chomp; $_ } <$fd>;
|
||||
close $fd or die_error(undef, "Reading git-diff-tree failed");
|
||||
|
||||
# read commitdiff
|
||||
my $fd;
|
||||
my @difftree;
|
||||
if ($format eq 'html') {
|
||||
open $fd, "-|", $GIT, "diff-tree", '-r', '-M', '-C',
|
||||
"--patch-with-raw", "--full-index", $hash_parent, $hash
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
|
||||
while (chomp(my $line = <$fd>)) {
|
||||
# empty line ends raw part of diff-tree output
|
||||
last unless $line;
|
||||
push @difftree, $line;
|
||||
}
|
||||
|
||||
} elsif ($format eq 'plain') {
|
||||
open $fd, "-|", $GIT, "diff-tree", '-r', '-p', '-B', $hash_parent, $hash
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
|
||||
} else {
|
||||
die_error(undef, "Unknown commitdiff format");
|
||||
}
|
||||
|
||||
# non-textual hash id's can be cached
|
||||
my $expires;
|
||||
if ($hash =~ m/^[0-9a-fA-F]{40}$/) {
|
||||
$expires = "+1d";
|
||||
}
|
||||
my $refs = git_get_references();
|
||||
my $ref = format_ref_marker($refs, $co{'id'});
|
||||
my $formats_nav =
|
||||
$cgi->a({-href => href(action=>"commitdiff_plain", hash=>$hash, hash_parent=>$hash_parent)},
|
||||
"plain");
|
||||
git_header_html(undef, $expires);
|
||||
git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);
|
||||
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash);
|
||||
print "<div class=\"page_body\">\n";
|
||||
git_print_simplified_log($co{'comment'}, 1); # skip title
|
||||
print "<br/>\n";
|
||||
foreach my $line (@difftree) {
|
||||
# ':100644 100644 03b218260e99b78c6df0ed378e59ed9205ccc96d 3b93d5e7cc7f7dd4ebed13a5cc1a4ad976fc94d8 M ls-files.c'
|
||||
# ':100644 100644 7f9281985086971d3877aca27704f2aaf9c448ce bc190ebc71bbd923f2b728e505408f5e54bd073a M rev-tree.c'
|
||||
if ($line !~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) {
|
||||
next;
|
||||
}
|
||||
my $from_mode = $1;
|
||||
my $to_mode = $2;
|
||||
my $from_id = $3;
|
||||
my $to_id = $4;
|
||||
my $status = $5;
|
||||
my $file = validate_input(unquote($6));
|
||||
if ($status eq "A") {
|
||||
print "<div class=\"diff_info\">" . file_type($to_mode) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$to_id, file_name=>$file)},
|
||||
$to_id) . "(new)" .
|
||||
"</div>\n";
|
||||
git_diff_print(undef, "/dev/null", $to_id, "b/$file");
|
||||
} elsif ($status eq "D") {
|
||||
print "<div class=\"diff_info\">" . file_type($from_mode) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$from_id, file_name=>$file)},
|
||||
$from_id) . "(deleted)" .
|
||||
"</div>\n";
|
||||
git_diff_print($from_id, "a/$file", undef, "/dev/null");
|
||||
} elsif ($status eq "M") {
|
||||
if ($from_id ne $to_id) {
|
||||
print "<div class=\"diff_info\">" .
|
||||
file_type($from_mode) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
|
||||
hash=>$from_id, file_name=>$file)},
|
||||
$from_id) .
|
||||
" -> " .
|
||||
file_type($to_mode) . ":" .
|
||||
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$to_id, file_name=>$file)},
|
||||
$to_id);
|
||||
print "</div>\n";
|
||||
git_diff_print($from_id, "a/$file", $to_id, "b/$file");
|
||||
}
|
||||
}
|
||||
}
|
||||
print "<br/>\n" .
|
||||
"</div>";
|
||||
git_footer_html();
|
||||
}
|
||||
|
||||
sub git_commitdiff_plain {
|
||||
mkdir($git_temp, 0700);
|
||||
my %co = parse_commit($hash);
|
||||
if (!%co) {
|
||||
die_error(undef, "Unknown commit object");
|
||||
}
|
||||
if (!defined $hash_parent) {
|
||||
$hash_parent = $co{'parent'} || '--root';
|
||||
}
|
||||
open my $fd, "-|", $GIT, "diff-tree", '-r', $hash_parent, $hash
|
||||
or die_error(undef, "Open git-diff-tree failed");
|
||||
my @difftree = map { chomp; $_ } <$fd>;
|
||||
close $fd or die_error(undef, "Reading diff-tree failed");
|
||||
# write commit message
|
||||
if ($format eq 'html') {
|
||||
my $refs = git_get_references();
|
||||
my $ref = format_ref_marker($refs, $co{'id'});
|
||||
my $formats_nav =
|
||||
$cgi->a({-href => href(action=>"commitdiff_plain",
|
||||
hash=>$hash, hash_parent=>$hash_parent)},
|
||||
"plain");
|
||||
|
||||
# try to figure out the next tag after this commit
|
||||
my $tagname;
|
||||
my $refs = git_get_references("tags");
|
||||
open $fd, "-|", $GIT, "rev-list", "HEAD";
|
||||
my @commits = map { chomp; $_ } <$fd>;
|
||||
close $fd;
|
||||
foreach my $commit (@commits) {
|
||||
if (defined $refs->{$commit}) {
|
||||
$tagname = $refs->{$commit}
|
||||
}
|
||||
if ($commit eq $hash) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
git_header_html(undef, $expires);
|
||||
git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);
|
||||
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash);
|
||||
print "<div class=\"page_body\">\n";
|
||||
print "<div class=\"log\">\n";
|
||||
git_print_simplified_log($co{'comment'}, 1); # skip title
|
||||
print "</div>\n"; # class="log"
|
||||
|
||||
print $cgi->header(-type => "text/plain",
|
||||
-charset => 'utf-8',
|
||||
-content_disposition => "inline; filename=\"git-$hash.patch\"");
|
||||
my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
|
||||
my $comment = $co{'comment'};
|
||||
print <<TEXT;
|
||||
} elsif ($format eq 'plain') {
|
||||
my $refs = git_get_references("tags");
|
||||
my $tagname = git_get_rev_name_tags($hash);
|
||||
my $filename = basename($project) . "-$hash.patch";
|
||||
|
||||
print $cgi->header(
|
||||
-type => 'text/plain',
|
||||
-charset => 'utf-8',
|
||||
-expires => $expires,
|
||||
-content_disposition => qq(inline; filename="$filename"));
|
||||
my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
|
||||
print <<TEXT;
|
||||
From: $co{'author'}
|
||||
Date: $ad{'rfc2822'} ($ad{'tz_local'})
|
||||
Subject: $co{'title'}
|
||||
TEXT
|
||||
if (defined $tagname) {
|
||||
print "X-Git-Tag: $tagname\n";
|
||||
}
|
||||
print "X-Git-Url: $my_url?p=$project;a=commitdiff;h=$hash\n" .
|
||||
"\n";
|
||||
print "X-Git-Tag: $tagname\n" if $tagname;
|
||||
print "X-Git-Url: " . $cgi->self_url() . "\n\n";
|
||||
|
||||
foreach my $line (@$comment) {;
|
||||
print "$line\n";
|
||||
foreach my $line (@{$co{'comment'}}) {
|
||||
print "$line\n";
|
||||
}
|
||||
print "---\n\n";
|
||||
}
|
||||
print "---\n\n";
|
||||
|
||||
foreach my $line (@difftree) {
|
||||
if ($line !~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) {
|
||||
next;
|
||||
}
|
||||
my $from_id = $3;
|
||||
my $to_id = $4;
|
||||
my $status = $5;
|
||||
my $file = $6;
|
||||
if ($status eq "A") {
|
||||
git_diff_print(undef, "/dev/null", $to_id, "b/$file", "plain");
|
||||
} elsif ($status eq "D") {
|
||||
git_diff_print($from_id, "a/$file", undef, "/dev/null", "plain");
|
||||
} elsif ($status eq "M") {
|
||||
git_diff_print($from_id, "a/$file", $to_id, "b/$file", "plain");
|
||||
}
|
||||
# write patch
|
||||
if ($format eq 'html') {
|
||||
#git_difftree_body(\@difftree, $hash, $hash_parent);
|
||||
#print "<br/>\n";
|
||||
|
||||
git_patchset_body($fd, \@difftree, $hash, $hash_parent);
|
||||
close $fd;
|
||||
print "</div>\n"; # class="page_body"
|
||||
git_footer_html();
|
||||
|
||||
} elsif ($format eq 'plain') {
|
||||
local $/ = undef;
|
||||
print <$fd>;
|
||||
close $fd
|
||||
or print "Reading git-diff-tree failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub git_commitdiff_plain {
|
||||
git_commitdiff('plain');
|
||||
}
|
||||
|
||||
sub git_history {
|
||||
if (!defined $hash_base) {
|
||||
$hash_base = git_get_head_hash($project);
|
||||
|
||||
Reference in New Issue
Block a user