Merge branch 'ds/doc' into jc/fmt-patch

* ds/doc:
  Update documentation for git-format-patch
  sha1_file: avoid re-preparing duplicate packs
  handle concurrent pruning of packed objects
  http: prevent segfault during curl handle reuse
  Remove possible segfault in http-fetch.
  gitk: show_error fix
  [PATCH] gitk: start-up bugfix
  [PATCH] gitk: Replace "git-" commands with "git "
  [PATCH] gitk: Display commit messages with word wrap
  gitk: Fix bug where page-up/down wouldn't always work properly
  gitk: Fix display of "(...)" for parents/children we haven't drawn
  send-email: only 'require' instead of 'use' Net::SMTP
  Allow multiple -m options to git-commit.
This commit is contained in:
Junio C Hamano 2006-06-02 18:17:35 -07:00
commit 2f164c35fa
7 changed files with 152 additions and 101 deletions

View File

@ -9,37 +9,46 @@ git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] [-s] [-c]
[--diff-options] <his> [<mine>]
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach]
[-s | --signoff] [--diff-options] [--start-number <n>]
<since>[..<until>]
DESCRIPTION
-----------
Prepare each commit with its patch since <mine> head forked from
<his> head, one file per patch formatted to resemble UNIX mailbox
format, for e-mail submission or use with gitlink:git-am[1].
Prepare each commit between <since> and <until> with its patch in
one file per commit, formatted to resemble UNIX mailbox format.
If ..<until> is not specified, the head of the current working
tree is implied.
The output of this command is convenient for e-mail submission or
for use with gitlink:git-am[1].
Each output file is numbered sequentially from 1, and uses the
first line of the commit message (massaged for pathname safety)
as the filename.
first line of the commit message (massaged for pathname safety) as
the filename. The names of the output files are printed to standard
output, unless the --stdout option is specified.
When -o is specified, output files are created in <dir>; otherwise
they are created in the current working directory. This option
is ignored if --stdout is specified.
If -o is specified, output files are created in <dir>. Otherwise
they are created in the current working directory.
When -n is specified, instead of "[PATCH] Subject", the first
line is formatted as "[PATCH N/M] Subject", unless you have only
one patch.
If -n is specified, instead of "[PATCH] Subject", the first line
is formatted as "[PATCH n/m] Subject".
OPTIONS
-------
-o|--output-directory <dir>::
Use <dir> to store the resulting files, instead of the
current working directory.
current working directory. This option is ignored if
--stdout is specified.
-n|--numbered::
Name output in '[PATCH n/m]' format.
--start-number <n>::
Start numbering the patches at <n> instead of 1.
-k|--keep-subject::
Do not strip/add '[PATCH]' from the first line of the
commit log message.
@ -48,17 +57,9 @@ OPTIONS
Add `Signed-off-by:` line to the commit message, using
the committer identity of yourself.
-c|--check::
Display suspicious lines in the patch. The definition
of 'suspicious lines' is currently the lines that has
trailing whitespaces, and the lines whose indentation
has a SP character immediately followed by a TAB
character.
--stdout::
This flag generates the mbox formatted output to the
standard output, instead of saving them into a file per
patch and implies --mbox.
Print all commits to the standard output in mbox format,
instead of creating a file for each one.
--attach::
Create attachments instead of inlining patches.
@ -82,18 +83,18 @@ git-format-patch -k --stdout R1..R2 | git-am -3 -k::
cherry-pick them.
git-format-patch origin::
Extract commits the current branch accumulated since it
pulled from origin the last time in a patch form for
e-mail submission.
Extract all commits which are in the current branch but
not in the origin branch. For each commit a separate file
is created in the current directory.
git-format-patch -M -B origin::
The same as the previous one, except detect and handle
renames and complete rewrites intelligently to produce
renaming patch. A renaming patch reduces the amount of
text output, and generally makes it easier to review
it. Note that the "patch" program does not understand
renaming patch well, so use it only when you know the
recipient uses git to apply your patch.
The same as the previous one. Additionally, it detects
and handles renames and complete rewrites intelligently to
produce a renaming patch. A renaming patch reduces the
amount of text output, and generally makes it easier to
review it. Note that the "patch" program does not
understand renaming patches, so use it only when you know
the recipient uses git to apply your patch.
See Also

View File

@ -260,20 +260,41 @@ do
-m|--m|--me|--mes|--mess|--messa|--messag|--message)
case "$#" in 1) usage ;; esac
shift
log_given=t$log_given
log_message="$1"
log_given=m$log_given
if test "$log_message" = ''
then
log_message="$1"
else
log_message="$log_message
$1"
fi
no_edit=t
shift
;;
-m*)
log_given=t$log_given
log_message=`expr "$1" : '-m\(.*\)'`
log_given=m$log_given
if test "$log_message" = ''
then
log_message=`expr "$1" : '-m\(.*\)'`
else
log_message="$log_message
`expr "$1" : '-m\(.*\)'`"
fi
no_edit=t
shift
;;
--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
log_given=t$log_given
log_message=`expr "$1" : '-[^=]*=\(.*\)'`
log_given=m$log_given
if test "$log_message" = ''
then
log_message=`expr "$1" : '-[^=]*=\(.*\)'`
else
log_message="$log_message
`expr "$1" : '-[^=]*=\(.*\)'`"
fi
no_edit=t
shift
;;
@ -378,7 +399,9 @@ esac
case "$log_given" in
tt*)
die "Only one of -c/-C/-F/-m can be used." ;;
die "Only one of -c/-C/-F can be used." ;;
*tm*|*mt*)
die "Option -m cannot be combined with -c/-C/-F." ;;
esac
case "$#,$also,$only,$amend" in

View File

@ -21,7 +21,6 @@ use warnings;
use Term::ReadLine;
use Getopt::Long;
use Data::Dumper;
use Net::SMTP;
# most mail servers generate the Date: header, but not all...
$ENV{LC_ALL} = 'C';
@ -394,6 +393,7 @@ X-Mailer: git-send-email $gitversion
print $sm "$header\n$message";
close $sm or die $?;
} else {
require Net::SMTP;
$smtp ||= Net::SMTP->new( $smtp_server );
$smtp->mail( $from ) or die $smtp->message;
$smtp->to( @recipients ) or die $smtp->message;

102
gitk
View File

@ -34,10 +34,10 @@ proc start_rev_list {view} {
set order "--date-order"
}
if {[catch {
set fd [open [concat | git-rev-list --header $order \
set fd [open [concat | git rev-list --header $order \
--parents --boundary --default HEAD $args] r]
} err]} {
puts stderr "Error executing git-rev-list: $err"
puts stderr "Error executing git rev-list: $err"
exit 1
}
set commfd($view) $fd
@ -94,10 +94,10 @@ proc getcommitlines {fd view} {
}
if {[string range $err 0 4] == "usage"} {
set err "Gitk: error reading commits$fv:\
bad arguments to git-rev-list."
bad arguments to git rev-list."
if {$viewname($view) eq "Command line"} {
append err \
" (Note: arguments to gitk are passed to git-rev-list\
" (Note: arguments to gitk are passed to git rev-list\
to allow selection of commits to be displayed.)"
}
} else {
@ -148,7 +148,7 @@ proc getcommitlines {fd view} {
if {[string length $shortcmit] > 80} {
set shortcmit "[string range $shortcmit 0 80]..."
}
error_popup "Can't parse git-rev-list output: {$shortcmit}"
error_popup "Can't parse git rev-list output: {$shortcmit}"
exit 1
}
set id [lindex $ids 0]
@ -217,7 +217,7 @@ proc doupdate {} {
}
proc readcommit {id} {
if {[catch {set contents [exec git-cat-file commit $id]}]} return
if {[catch {set contents [exec git cat-file commit $id]}]} return
parsecommit $id $contents 0
}
@ -276,8 +276,8 @@ proc parsecommit {id contents listed} {
set headline $comment
}
if {!$listed} {
# git-rev-list indents the comment by 4 spaces;
# if we got this via git-cat-file, add the indentation
# git rev-list indents the comment by 4 spaces;
# if we got this via git cat-file, add the indentation
set newcomment {}
foreach line [split $comment "\n"] {
append newcomment " "
@ -337,14 +337,14 @@ proc readrefs {} {
set type {}
set tag {}
catch {
set commit [exec git-rev-parse "$id^0"]
set commit [exec git rev-parse "$id^0"]
if {"$commit" != "$id"} {
set tagids($name) $commit
lappend idtags($commit) $name
}
}
catch {
set tagcontents($name) [exec git-cat-file tag "$id"]
set tagcontents($name) [exec git cat-file tag "$id"]
}
} elseif { $type == "heads" } {
set headids($name) $id
@ -357,21 +357,21 @@ proc readrefs {} {
close $refd
}
proc show_error {w msg} {
proc show_error {w top msg} {
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
button $w.ok -text OK -command "destroy $w"
button $w.ok -text OK -command "destroy $top"
pack $w.ok -side bottom -fill x
bind $w <Visibility> "grab $w; focus $w"
bind $w <Key-Return> "destroy $w"
tkwait window $w
bind $top <Visibility> "grab $top; focus $top"
bind $top <Key-Return> "destroy $top"
tkwait window $top
}
proc error_popup msg {
set w .error
toplevel $w
wm transient $w .
show_error $w $msg
show_error $w $w $msg
}
proc makewindow {} {
@ -380,7 +380,7 @@ proc makewindow {} {
global findtype findtypemenu findloc findstring fstring geometry
global entries sha1entry sha1string sha1but
global maincursor textcursor curtextcursor
global rowctxmenu mergemax
global rowctxmenu mergemax wrapcomment
menu .bar
.bar add cascade -label "File" -menu .bar.file
@ -527,6 +527,7 @@ proc makewindow {} {
pack $ctext -side left -fill both -expand 1
.ctop.cdet add .ctop.cdet.left
$ctext tag conf comment -wrap $wrapcomment
$ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
$ctext tag conf hunksep -fore blue
$ctext tag conf d0 -fore red
@ -696,7 +697,7 @@ proc savestuff {w} {
global stuffsaved findmergefiles maxgraphpct
global maxwidth
global viewname viewfiles viewargs viewperm nextviewnum
global cmitmode
global cmitmode wrapcomment
if {$stuffsaved} return
if {![winfo viewable .]} return
@ -709,6 +710,7 @@ proc savestuff {w} {
puts $f [list set maxgraphpct $maxgraphpct]
puts $f [list set maxwidth $maxwidth]
puts $f [list set cmitmode $cmitmode]
puts $f [list set wrapcomment $wrapcomment]
puts $f "set geometry(width) [winfo width .ctop]"
puts $f "set geometry(height) [winfo height .ctop]"
puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]"
@ -1285,7 +1287,7 @@ proc vieweditor {top n title} {
checkbutton $top.perm -text "Remember this view" -variable newviewperm($n)
grid $top.perm - -pady 5 -sticky w
message $top.al -aspect 1000 -font $uifont \
-text "Commits to include (arguments to git-rev-list):"
-text "Commits to include (arguments to git rev-list):"
grid $top.al - -sticky w -pady 5
entry $top.args -width 50 -textvariable newviewargs($n) \
-background white
@ -2939,7 +2941,7 @@ proc findpatches {} {
}
if {[catch {
set f [open [list | git-diff-tree --stdin -s -r -S$findstring \
set f [open [list | git diff-tree --stdin -s -r -S$findstring \
<< $inputids] r]
} err]} {
error_popup "Error starting search process: $err"
@ -2971,7 +2973,7 @@ proc readfindproc {} {
return
}
if {![regexp {^[0-9a-f]{40}} $line id]} {
error_popup "Can't parse git-diff-tree output: $line"
error_popup "Can't parse git diff-tree output: $line"
stopfindproc
return
}
@ -3036,10 +3038,10 @@ proc findfiles {} {
if {$l == $findstartline} break
}
# start off a git-diff-tree process if needed
# start off a git diff-tree process if needed
if {$diffsneeded ne {}} {
if {[catch {
set df [open [list | git-diff-tree -r --stdin << $diffsneeded] r]
set df [open [list | git diff-tree -r --stdin << $diffsneeded] r]
} err ]} {
error_popup "Error starting search process: $err"
return
@ -3069,7 +3071,7 @@ proc readfilediffs {df} {
if {[catch {close $df} err]} {
stopfindproc
bell
error_popup "Error in git-diff-tree: $err"
error_popup "Error in git diff-tree: $err"
} elseif {[info exists findid]} {
set id $findid
stopfindproc
@ -3096,7 +3098,7 @@ proc donefilediff {} {
if {[info exists fdiffid]} {
while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffid
&& $fdiffpos < [llength $fdiffsneeded]} {
# git-diff-tree doesn't output anything for a commit
# git diff-tree doesn't output anything for a commit
# which doesn't change anything
set nullid [lindex $fdiffsneeded $fdiffpos]
set treediffs($nullid) {}
@ -3213,8 +3215,11 @@ proc selcanvline {w x y} {
proc commit_descriptor {p} {
global commitinfo
if {![info exists commitinfo($p)]} {
getcommit $p
}
set l "..."
if {[info exists commitinfo($p)]} {
if {[llength $commitinfo($p)] > 1} {
set l [lindex $commitinfo($p) 0]
}
return "$p ($l)"
@ -3222,11 +3227,11 @@ proc commit_descriptor {p} {
# append some text to the ctext widget, and make any SHA1 ID
# that we know about be a clickable link.
proc appendwithlinks {text} {
proc appendwithlinks {text tags} {
global ctext commitrow linknum curview
set start [$ctext index "end - 1c"]
$ctext insert end $text
$ctext insert end $text $tags
$ctext insert end "\n"
set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
foreach l $links {
@ -3354,7 +3359,7 @@ proc selectline {l isnew} {
$ctext insert end "\n"
}
set comment {}
set headers {}
set olds [lindex $parentlist $l]
if {[llength $olds] > 1} {
set np 0
@ -3365,23 +3370,22 @@ proc selectline {l isnew} {
set tag m$np
}
$ctext insert end "Parent: " $tag
appendwithlinks [commit_descriptor $p]
appendwithlinks [commit_descriptor $p] {}
incr np
}
} else {
foreach p $olds {
append comment "Parent: [commit_descriptor $p]\n"
append headers "Parent: [commit_descriptor $p]\n"
}
}
foreach c [lindex $childlist $l] {
append comment "Child: [commit_descriptor $c]\n"
append headers "Child: [commit_descriptor $c]\n"
}
append comment "\n"
append comment [lindex $info 5]
# make anything that looks like a SHA1 ID be a clickable link
appendwithlinks $comment
appendwithlinks $headers {}
appendwithlinks [lindex $info 5] {comment}
$ctext tag delete Comments
$ctext tag remove found 1.0 end
@ -3426,6 +3430,7 @@ proc selnextpage {dir} {
set lpp 1
}
allcanvs yview scroll [expr {$dir * $lpp}] units
drawvisible
if {![info exists selectedline]} return
set l [expr {$selectedline + $dir * $lpp}]
if {$l < 0} {
@ -3521,7 +3526,7 @@ proc gettree {id} {
catch {unset diffmergeid}
if {![info exists treefilelist($id)]} {
if {![info exists treepending]} {
if {[catch {set gtf [open [concat | git-ls-tree -r $id] r]}]} {
if {[catch {set gtf [open [concat | git ls-tree -r $id] r]}]} {
return
}
set treepending $id
@ -3569,7 +3574,7 @@ proc showfile {f} {
return
}
set blob [lindex $treeidlist($diffids) $i]
if {[catch {set bf [open [concat | git-cat-file blob $blob] r]} err]} {
if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
puts "oops, error reading blob $blob: $err"
return
}
@ -3611,7 +3616,7 @@ proc mergediff {id l} {
set diffids $id
# this doesn't seem to actually affect anything...
set env(GIT_DIFF_OPTS) $diffopts
set cmd [concat | git-diff-tree --no-commit-id --cc $id]
set cmd [concat | git diff-tree --no-commit-id --cc $id]
if {[catch {set mdf [open $cmd r]} err]} {
error_popup "Error getting merge diffs: $err"
return
@ -3723,7 +3728,7 @@ proc gettreediffs {ids} {
set treepending $ids
set treediff {}
if {[catch \
{set gdtf [open [concat | git-diff-tree --no-commit-id -r $ids] r]} \
{set gdtf [open [concat | git diff-tree --no-commit-id -r $ids] r]} \
]} return
fconfigure $gdtf -blocking 0
fileevent $gdtf readable [list gettreediffline $gdtf $ids]
@ -3759,7 +3764,7 @@ proc getblobdiffs {ids} {
global nextupdate diffinhdr treediffs
set env(GIT_DIFF_OPTS) $diffopts
set cmd [concat | git-diff-tree --no-commit-id -r -p -C $ids]
set cmd [concat | git diff-tree --no-commit-id -r -p -C $ids]
if {[catch {set bdf [open $cmd r]} err]} {
puts "error getting diffs: $err"
return
@ -4296,7 +4301,7 @@ proc mkpatchgo {} {
set oldid [$patchtop.fromsha1 get]
set newid [$patchtop.tosha1 get]
set fname [$patchtop.fname get]
if {[catch {exec git-diff-tree -p $oldid $newid >$fname &} err]} {
if {[catch {exec git diff-tree -p $oldid $newid >$fname &} err]} {
error_popup "Error creating patch: $err"
}
catch {destroy $patchtop}
@ -4504,7 +4509,7 @@ proc showtag {tag isnew} {
} else {
set text "Tag: $tag\nId: $tagids($tag)"
}
appendwithlinks $text
appendwithlinks $text {}
$ctext conf -state disabled
init_flist {}
}
@ -4863,11 +4868,11 @@ proc tcl_encoding {enc} {
# defaults...
set datemode 0
set diffopts "-U 5 -p"
set wrcomcmd "git-diff-tree --stdin -p --pretty"
set wrcomcmd "git diff-tree --stdin -p --pretty"
set gitencoding {}
catch {
set gitencoding [exec git-repo-config --get i18n.commitencoding]
set gitencoding [exec git repo-config --get i18n.commitencoding]
}
if {$gitencoding == ""} {
set gitencoding "utf-8"
@ -4890,6 +4895,7 @@ set downarrowlen 7
set mingaplen 30
set flistmode "flat"
set cmitmode "patch"
set wrapcomment "none"
set colors {green red blue magenta darkgrey brown orange}
@ -4911,7 +4917,7 @@ foreach arg $argv {
# check that we can find a .git directory somewhere...
set gitdir [gitdir]
if {![file isdirectory $gitdir]} {
show_error . "Cannot find the git directory \"$gitdir\"."
show_error {} . "Cannot find the git directory \"$gitdir\"."
exit 1
}
@ -4922,7 +4928,7 @@ if {$i >= 0} {
set revtreeargs [lrange $revtreeargs 0 [expr {$i - 1}]]
} elseif {$revtreeargs ne {}} {
if {[catch {
set f [eval exec git-rev-parse --no-revs --no-flags $revtreeargs]
set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
set cmdline_files [split $f "\n"]
set n [llength $cmdline_files]
set revtreeargs [lrange $revtreeargs 0 end-$n]
@ -4931,9 +4937,9 @@ if {$i >= 0} {
# so look for "fatal:".
set i [string first "fatal:" $err]
if {$i > 0} {
set err [string range [expr {$i + 6}] end]
set err [string range $err [expr {$i + 6}] end]
}
show_error . "Bad arguments to gitk:\n$err"
show_error {} . "Bad arguments to gitk:\n$err"
exit 1
}
}

View File

@ -1269,10 +1269,10 @@ int main(int argc, char **argv)
if (pull(commit_id))
rc = 1;
curl_slist_free_all(no_pragma_header);
http_cleanup();
curl_slist_free_all(no_pragma_header);
if (corrupt_object_found) {
fprintf(stderr,
"Some loose object were found to be corrupt, but they might be just\n"

9
http.c
View File

@ -25,7 +25,6 @@ long curl_low_speed_limit = -1;
long curl_low_speed_time = -1;
struct curl_slist *pragma_header;
struct curl_slist *no_range_header;
struct active_request_slot *active_queue_head = NULL;
@ -208,7 +207,6 @@ void http_init(void)
curl_global_init(CURL_GLOBAL_ALL);
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
no_range_header = curl_slist_append(no_range_header, "Range:");
#ifdef USE_CURL_MULTI
{
@ -344,9 +342,14 @@ struct active_request_slot *get_active_slot(void)
slot->finished = NULL;
slot->callback_data = NULL;
slot->callback_func = NULL;
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
return slot;
}

View File

@ -617,6 +617,12 @@ static void prepare_packed_git_one(char *objdir, int local)
/* we have .idx. Is it a file we can map? */
strcpy(path + len, de->d_name);
for (p = packed_git; p; p = p->next) {
if (!memcmp(path, p->pack_name, len + namelen - 4))
break;
}
if (p)
continue;
p = add_packed_git(path, len + namelen, local);
if (!p)
continue;
@ -626,12 +632,12 @@ static void prepare_packed_git_one(char *objdir, int local)
closedir(dir);
}
static int prepare_packed_git_run_once = 0;
void prepare_packed_git(void)
{
static int run_once = 0;
struct alternate_object_database *alt;
if (run_once)
if (prepare_packed_git_run_once)
return;
prepare_packed_git_one(get_object_directory(), 1);
prepare_alt_odb();
@ -640,7 +646,13 @@ void prepare_packed_git(void)
prepare_packed_git_one(alt->base, 0);
alt->name[-1] = '/';
}
run_once = 1;
prepare_packed_git_run_once = 1;
}
static void reprepare_packed_git(void)
{
prepare_packed_git_run_once = 0;
prepare_packed_git();
}
int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
@ -1212,9 +1224,12 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep
if (!map) {
struct pack_entry e;
if (!find_pack_entry(sha1, &e))
return error("unable to find %s", sha1_to_hex(sha1));
return packed_object_info(&e, type, sizep);
if (find_pack_entry(sha1, &e))
return packed_object_info(&e, type, sizep);
reprepare_packed_git();
if (find_pack_entry(sha1, &e))
return packed_object_info(&e, type, sizep);
return error("unable to find %s", sha1_to_hex(sha1));
}
if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
status = error("unable to unpack %s header",
@ -1256,6 +1271,9 @@ void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size
munmap(map, mapsize);
return buf;
}
reprepare_packed_git();
if (find_pack_entry(sha1, &e))
return read_packed_sha1(sha1, type, size);
return NULL;
}