Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
git
提交
5401f304
G
git
项目概览
李少辉-开发者
/
git
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
git
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5401f304
编写于
11月 30, 2005
作者:
J
Junio C Hamano
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'jc/apply', 'lt/ls-tree', 'lt/bisect' and 'lt/merge'
上级
0738fc21
830273d1
246cc52f
e9a45d75
0501c240
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
215 addition
and
320 deletion
+215
-320
Documentation/git-diff-files.txt
Documentation/git-diff-files.txt
+9
-0
Documentation/tutorial.txt
Documentation/tutorial.txt
+7
-8
diff-files.c
diff-files.c
+36
-7
git-applymbox.sh
git-applymbox.sh
+1
-1
git-applypatch.sh
git-applypatch.sh
+24
-13
git-bisect.sh
git-bisect.sh
+22
-7
git-format-patch.sh
git-format-patch.sh
+6
-3
git-merge-one-file.sh
git-merge-one-file.sh
+1
-5
git-merge-recursive.py
git-merge-recursive.py
+0
-2
ls-tree.c
ls-tree.c
+42
-202
rev-list.c
rev-list.c
+12
-6
t/t0000-basic.sh
t/t0000-basic.sh
+2
-3
t/t3100-ls-tree-restrict.sh
t/t3100-ls-tree-restrict.sh
+12
-23
t/t3101-ls-tree-dirname.sh
t/t3101-ls-tree-dirname.sh
+8
-30
tree.c
tree.c
+24
-10
tree.h
tree.h
+9
-0
未找到文件。
Documentation/git-diff-files.txt
浏览文件 @
5401f304
...
...
@@ -21,6 +21,15 @@ OPTIONS
-------
include::diff-options.txt[]
-1 -2 -3 or --base --ours --theirs, and -0::
Diff against the "base" version, "our branch" or "their
branch" respectively. With these options, diffs for
merged entries are not shown.
+
The default is to diff against our branch (-2) and the
cleanly resolved paths. The option -0 can be given to
omit diff output for unmerged entries and just show "Unmerged".
-q::
Remain silent even on nonexisting files
...
...
Documentation/tutorial.txt
浏览文件 @
5401f304
...
...
@@ -898,9 +898,8 @@ file, which had no differences in the `mybranch` branch), and say:
fatal: Merge requires file-level merging
Nope.
...
merge: warning: conflicts during merge
ERROR: Merge conflict in hello.
fatal: merge program failed
Auto-merging hello
CONFLICT (content): Merge conflict in hello
Automatic merge failed/prevented; fix up by hand
----------------
...
...
@@ -942,10 +941,10 @@ environment, is `git show-branch`.
------------------------------------------------
$ git show-branch master mybranch
* [master] Merge
d "mybranch" changes.
* [master] Merge
work in mybranch
! [mybranch] Some work.
--
+ [master] Merge
d "mybranch" changes.
+ [master] Merge
work in mybranch
++ [mybranch] Some work.
------------------------------------------------
...
...
@@ -998,10 +997,10 @@ looks like, or run `show-branch`, which tells you this.
------------------------------------------------
$ git show-branch master mybranch
! [master] Merge
d "mybranch" changes.
* [mybranch] Merge
d "mybranch" changes.
! [master] Merge
work in mybranch
* [mybranch] Merge
work in mybranch
--
++ [master] Merge
d "mybranch" changes.
++ [master] Merge
work in mybranch
------------------------------------------------
...
...
diff-files.c
浏览文件 @
5401f304
...
...
@@ -7,12 +7,12 @@
#include "diff.h"
static
const
char
diff_files_usage
[]
=
"git-diff-files [-q] "
"[<common diff options>] [<path>...]"
"git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP
;
static
struct
diff_options
diff_options
;
static
int
silent
=
0
;
static
int
diff_unmerged_stage
=
2
;
static
void
show_unmerge
(
const
char
*
path
)
{
...
...
@@ -46,7 +46,21 @@ int main(int argc, const char **argv)
argc
--
;
break
;
}
if
(
!
strcmp
(
argv
[
1
],
"-q"
))
if
(
!
strcmp
(
argv
[
1
],
"-0"
))
diff_unmerged_stage
=
0
;
else
if
(
!
strcmp
(
argv
[
1
],
"-1"
))
diff_unmerged_stage
=
1
;
else
if
(
!
strcmp
(
argv
[
1
],
"-2"
))
diff_unmerged_stage
=
2
;
else
if
(
!
strcmp
(
argv
[
1
],
"-3"
))
diff_unmerged_stage
=
3
;
else
if
(
!
strcmp
(
argv
[
1
],
"--base"
))
diff_unmerged_stage
=
1
;
else
if
(
!
strcmp
(
argv
[
1
],
"--ours"
))
diff_unmerged_stage
=
2
;
else
if
(
!
strcmp
(
argv
[
1
],
"--theirs"
))
diff_unmerged_stage
=
3
;
else
if
(
!
strcmp
(
argv
[
1
],
"-q"
))
silent
=
1
;
else
if
(
!
strcmp
(
argv
[
1
],
"-r"
))
;
/* no-op */
...
...
@@ -95,11 +109,26 @@ int main(int argc, const char **argv)
if
(
ce_stage
(
ce
))
{
show_unmerge
(
ce
->
name
);
while
(
i
<
entries
&&
!
strcmp
(
ce
->
name
,
active_cache
[
i
]
->
name
))
while
(
i
<
entries
)
{
struct
cache_entry
*
nce
=
active_cache
[
i
];
if
(
strcmp
(
ce
->
name
,
nce
->
name
))
break
;
/* diff against the proper unmerged stage */
if
(
ce_stage
(
nce
)
==
diff_unmerged_stage
)
ce
=
nce
;
i
++
;
i
--
;
/* compensate for loop control increments */
continue
;
}
/*
* Compensate for loop update
*/
i
--
;
/*
* Show the diff for the 'ce' if we found the one
* from the desired stage.
*/
if
(
ce_stage
(
ce
)
!=
diff_unmerged_stage
)
continue
;
}
if
(
lstat
(
ce
->
name
,
&
st
)
<
0
)
{
...
...
git-applymbox.sh
浏览文件 @
5401f304
...
...
@@ -33,7 +33,7 @@ do
-k
)
keep_subject
=
-k
;;
-q
)
query_apply
=
t
;;
-c
)
continue
=
"
$2
"
;
resume
=
f
;
shift
;;
-m
)
fallback_3way
=
t
;;
-m
)
fall
_
back_3way
=
t
;;
-
*
)
usage
;;
*
)
break
;;
esac
...
...
git-applypatch.sh
浏览文件 @
5401f304
...
...
@@ -120,26 +120,36 @@ git-apply --index "$PATCHFILE" || {
O_OBJECT
=
`
cd
"
$GIT_OBJECT_DIRECTORY
"
&&
pwd
`
rm
-fr
.patch-merge-
*
if
git-apply
-z
--index-info
"
$PATCHFILE
"
\
>
.patch-merge-index-info 2>/dev/null
&&
GIT_INDEX_FILE
=
.patch-merge-tmp-index
\
git-update-index
-z
--index-info
<.patch-merge-index-info
&&
GIT_INDEX_FILE
=
.patch-merge-tmp-index
\
git-write-tree
>
.patch-merge-tmp-base
&&
(
mkdir
.patch-merge-tmp-dir
&&
cd
.patch-merge-tmp-dir
&&
GIT_INDEX_FILE
=
"../.patch-merge-tmp-index"
\
GIT_OBJECT_DIRECTORY
=
"
$O_OBJECT
"
\
git-apply
$binary
--index
)
<
"
$PATCHFILE
"
then
echo
Using index info to reconstruct a base tree...
mv
.patch-merge-tmp-base .patch-merge-base
mv
.patch-merge-tmp-index .patch-merge-index
else
(
N
=
10
# if the patch records the base tree...
sed
-ne
'
/^diff /q
/^applies-to: \([0-9a-f]*\)$/{
s//\1/p
q
}
'
"
$PATCHFILE
"
# or hoping the patch is against our recent commits...
# Otherwise, try nearby trees that can be used to apply the
# patch.
git-rev-list
--max-count
=
$N
HEAD
# or hoping the patch is against known tags...
git-ls-remote
--tags
.
)
|
while
read
base junk
do
while
read
base junk
do
# Try it if we have it as a tree.
git-cat-file tree
"
$base
"
>
/dev/null 2>&1
||
continue
...
...
@@ -155,7 +165,8 @@ git-apply --index "$PATCHFILE" || {
mv
../.patch-merge-tmp-index ../.patch-merge-index
&&
echo
"
$base
"
>
../.patch-merge-base
)
<
"
$PATCHFILE
"
2>/dev/null
&&
break
done
done
fi
test
-f
.patch-merge-index
&&
his_tree
=
$(
GIT_INDEX_FILE
=
.patch-merge-index git-write-tree
)
&&
...
...
git-bisect.sh
浏览文件 @
5401f304
#!/bin/sh
.
git-sh-setup
sq
()
{
perl
-e
'
for (@ARGV) {
s/'
\'
'/'
\'\\\\\'\'
'/g;
print " '
\'
'$_'
\'
'";
}
print "\n";
'
"
$@
"
}
usage
()
{
echo
>
&2
'usage: git bisect [start|bad|good|next|reset|visualize]
git bisect start
reset bisect state and start bisection.
git bisect start
[<pathspec>]
reset bisect state and start bisection.
git bisect bad [<rev>] mark <rev> a known-bad revision.
git bisect good [<rev>...] mark <rev>... known-good revisions.
git bisect next find next bisection to test and check it out.
...
...
@@ -33,7 +43,6 @@ bisect_autostart() {
}
bisect_start
()
{
case
"$#"
in
0
)
;;
*
)
usage
;;
esac
#
# Verify HEAD. If we were bisecting before this, reset to the
# top-of-line master first!
...
...
@@ -57,7 +66,11 @@ bisect_start() {
rm
-f
"
$GIT_DIR
/refs/heads/bisect"
rm
-rf
"
$GIT_DIR
/refs/bisect/"
mkdir
"
$GIT_DIR
/refs/bisect"
echo
"git-bisect start"
>
"
$GIT_DIR
/BISECT_LOG"
{
echo
-n
"git-bisect start"
sq
"
$@
"
}
>
"
$GIT_DIR
/BISECT_LOG"
sq
"
$@
"
>
"
$GIT_DIR
/BISECT_NAMES"
}
bisect_bad
()
{
...
...
@@ -121,7 +134,7 @@ bisect_next() {
bad
=
$(
git-rev-parse
--verify
refs/bisect/bad
)
&&
good
=
$(
git-rev-parse
--sq
--revs-only
--not
\
$(
cd
"
$GIT_DIR
"
&&
ls
refs/bisect/good-
*
))
&&
rev
=
$(
eval
"git-rev-list --bisect
$good
$bad
"
)
||
exit
rev
=
$(
eval
"git-rev-list --bisect
$good
$bad
--
$(
cat
$GIT_DIR
/BISECT_NAMES
)
"
)
||
exit
if
[
-z
"
$rev
"
]
;
then
echo
"
$bad
was both good and bad"
exit
1
...
...
@@ -131,7 +144,7 @@ bisect_next() {
git-diff-tree
--pretty
$rev
exit
0
fi
nr
=
$(
eval
"git-rev-list
$rev
$good
"
|
wc
-l
)
||
exit
nr
=
$(
eval
"git-rev-list
$rev
$good
--
$(
cat
$GIT_DIR
/BISECT_NAMES
)
"
|
wc
-l
)
||
exit
echo
"Bisecting:
$nr
revisions left to test after this"
echo
"
$rev
"
>
"
$GIT_DIR
/refs/heads/new-bisect"
git checkout new-bisect
||
exit
...
...
@@ -142,7 +155,8 @@ bisect_next() {
bisect_visualize
()
{
bisect_next_check fail
gitk bisect/bad
--not
`
cd
"
$GIT_DIR
/refs"
&&
echo
bisect/good-
*
`
not
=
`
cd
"
$GIT_DIR
/refs"
&&
echo
bisect/good-
*
`
eval
gitk bisect/bad
--not
$not
--
$(
cat
"
$GIT_DIR
/BISECT_NAMES"
)
}
bisect_reset
()
{
...
...
@@ -173,7 +187,8 @@ bisect_replay () {
test
"
$bisect
"
=
"git-bisect"
||
continue
case
"
$command
"
in
start
)
bisect_start
cmd
=
"bisect_start
$rev
"
eval
"
$cmd
"
;;
good
)
echo
"
$rev
"
>
"
$GIT_DIR
/refs/bisect/good-
$rev
"
...
...
git-format-patch.sh
浏览文件 @
5401f304
...
...
@@ -5,6 +5,10 @@
.
git-sh-setup
# Force diff to run in C locale.
LANG
=
C
LC_ALL
=
C
export
LANG LC_ALL
usage
()
{
echo
>
&2
"usage:
$0
"
' [-n] [-o dir | --stdout] [--keep-subject] [--mbox]
[--check] [--signoff] [-<diff options>...]
...
...
@@ -202,7 +206,7 @@ process_one () {
;;
esac
eval
"
$(
LANG
=
C
LC_ALL
=
C
sed
-ne
"
$whosepatchScript
"
$commsg
)
"
eval
"
$(
sed
-ne
"
$whosepatchScript
"
$commsg
)
"
test
"
$author
,
$au
"
=
",
$me
"
||
{
mailScript
=
"
$mailScript
"
'
a\
...
...
@@ -238,9 +242,8 @@ Date: '"$ad"
echo
git-diff-tree
-p
$diff_opts
"
$commit
"
| git-apply
--stat
--summary
echo
git-cat-file commit
"
$commit
^"
|
sed
-e
's/^tree /applies-to: /'
-e
q
git-diff-tree
-p
$diff_opts
"
$commit
"
echo
"--
-
"
echo
"--
"
echo
"@@GIT_VERSION@@"
case
"
$mbox
"
in
...
...
git-merge-one-file.sh
浏览文件 @
5401f304
...
...
@@ -79,11 +79,7 @@ case "${1:-.}${2:-.}${3:-.}" in
;;
esac
# We reset the index to the first branch, making
# git-diff-file useful
git-update-index
--add
--cacheinfo
"
$6
"
"
$2
"
"
$4
"
git-checkout-index
-u
-f
--
"
$4
"
&&
merge
"
$4
"
"
$orig
"
"
$src2
"
merge
"
$4
"
"
$orig
"
"
$src2
"
ret
=
$?
rm
-f
--
"
$orig
"
"
$src2
"
...
...
git-merge-recursive.py
浏览文件 @
5401f304
...
...
@@ -828,8 +828,6 @@ def processEntry(entry, branch1Name, branch2Name):
if
cacheOnly
:
updateFile
(
False
,
sha
,
mode
,
path
)
else
:
updateFileExt
(
aSha
,
aMode
,
path
,
updateCache
=
True
,
updateWd
=
False
)
updateFileExt
(
sha
,
mode
,
path
,
updateCache
=
False
,
updateWd
=
True
)
else
:
die
(
"ERROR: Fatal merge failure, shouldn't happen."
)
...
...
ls-tree.c
浏览文件 @
5401f304
...
...
@@ -12,218 +12,56 @@ static int line_termination = '\n';
#define LS_RECURSIVE 1
#define LS_TREE_ONLY 2
static
int
ls_options
=
0
;
const
char
**
pathspec
;
static
struct
tree_entry_list
root_entry
;
static
void
prepare_root
(
unsigned
char
*
sha1
)
{
unsigned
char
rsha
[
20
];
unsigned
long
size
;
void
*
buf
;
struct
tree
*
root_tree
;
buf
=
read_object_with_reference
(
sha1
,
"tree"
,
&
size
,
rsha
);
free
(
buf
);
if
(
!
buf
)
die
(
"Could not read %s"
,
sha1_to_hex
(
sha1
));
root_tree
=
lookup_tree
(
rsha
);
if
(
!
root_tree
)
die
(
"Could not read %s"
,
sha1_to_hex
(
sha1
));
/* Prepare a fake entry */
root_entry
.
directory
=
1
;
root_entry
.
executable
=
root_entry
.
symlink
=
0
;
root_entry
.
mode
=
S_IFDIR
;
root_entry
.
name
=
""
;
root_entry
.
item
.
tree
=
root_tree
;
root_entry
.
parent
=
NULL
;
}
static
int
prepare_children
(
struct
tree_entry_list
*
elem
)
{
if
(
!
elem
->
directory
)
return
-
1
;
if
(
!
elem
->
item
.
tree
->
object
.
parsed
)
{
struct
tree_entry_list
*
e
;
if
(
parse_tree
(
elem
->
item
.
tree
))
return
-
1
;
/* Set up the parent link */
for
(
e
=
elem
->
item
.
tree
->
entries
;
e
;
e
=
e
->
next
)
e
->
parent
=
elem
;
}
return
0
;
}
static
const
char
ls_tree_usage
[]
=
"git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"
;
static
struct
tree_entry_list
*
find_entry
(
const
char
*
path
,
char
*
pathbuf
)
static
int
show_tree
(
unsigned
char
*
sha1
,
const
char
*
base
,
int
baselen
,
const
char
*
pathname
,
unsigned
mode
,
int
stage
)
{
const
char
*
next
,
*
slash
;
int
len
;
struct
tree_entry_list
*
elem
=
&
root_entry
,
*
oldelem
=
NULL
;
*
(
pathbuf
)
=
'\0'
;
/* Find tree element, descending from root, that
* corresponds to the named path, lazily expanding
* the tree if possible.
*/
while
(
path
)
{
/* The fact we still have path means that the caller
* wants us to make sure that elem at this point is a
* directory, and possibly descend into it. Even what
* is left is just trailing slashes, we loop back to
* here, and this call to prepare_children() will
* catch elem not being a tree. Nice.
*/
if
(
prepare_children
(
elem
))
return
NULL
;
slash
=
strchr
(
path
,
'/'
);
if
(
!
slash
)
{
len
=
strlen
(
path
);
next
=
NULL
;
}
else
{
next
=
slash
+
1
;
len
=
slash
-
path
;
}
if
(
len
)
{
if
(
oldelem
)
{
pathbuf
+=
sprintf
(
pathbuf
,
"%s/"
,
oldelem
->
name
);
}
/* (len == 0) if the original path was "drivers/char/"
* and we have run already two rounds, having elem
* pointing at the drivers/char directory.
*/
elem
=
elem
->
item
.
tree
->
entries
;
while
(
elem
)
{
if
((
strlen
(
elem
->
name
)
==
len
)
&&
!
strncmp
(
elem
->
name
,
path
,
len
))
{
/* found */
const
char
*
type
=
"blob"
;
if
(
S_ISDIR
(
mode
))
{
const
char
**
s
;
if
(
ls_options
&
LS_RECURSIVE
)
return
READ_TREE_RECURSIVE
;
s
=
pathspec
;
if
(
s
)
{
for
(;;)
{
const
char
*
spec
=
*
s
++
;
int
len
,
speclen
;
if
(
!
spec
)
break
;
}
elem
=
elem
->
next
;
if
(
strncmp
(
base
,
spec
,
baselen
))
continue
;
len
=
strlen
(
pathname
);
spec
+=
baselen
;
speclen
=
strlen
(
spec
);
if
(
speclen
<=
len
)
continue
;
if
(
memcmp
(
pathname
,
spec
,
len
))
continue
;
return
READ_TREE_RECURSIVE
;
}
if
(
!
elem
)
return
NULL
;
oldelem
=
elem
;
}
path
=
next
;
type
=
"tree"
;
}
return
elem
;
}
static
const
char
*
entry_type
(
struct
tree_entry_list
*
e
)
{
return
(
e
->
directory
?
"tree"
:
"blob"
);
}
static
const
char
*
entry_hex
(
struct
tree_entry_list
*
e
)
{
return
sha1_to_hex
(
e
->
directory
?
e
->
item
.
tree
->
object
.
sha1
:
e
->
item
.
blob
->
object
.
sha1
);
}
/* forward declaration for mutually recursive routines */
static
int
show_entry
(
struct
tree_entry_list
*
,
int
,
char
*
pathbuf
);
static
int
show_children
(
struct
tree_entry_list
*
e
,
int
level
,
char
*
pathbuf
)
{
int
oldlen
=
strlen
(
pathbuf
);
if
(
e
!=
&
root_entry
)
sprintf
(
pathbuf
+
oldlen
,
"%s/"
,
e
->
name
);
if
(
prepare_children
(
e
))
die
(
"internal error: ls-tree show_children called with non tree"
);
e
=
e
->
item
.
tree
->
entries
;
while
(
e
)
{
show_entry
(
e
,
level
,
pathbuf
);
e
=
e
->
next
;
}
pathbuf
[
oldlen
]
=
'\0'
;
printf
(
"%06o %s %s
\t
"
,
mode
,
type
,
sha1_to_hex
(
sha1
));
write_name_quoted
(
base
,
baselen
,
pathname
,
line_termination
,
stdout
);
putchar
(
line_termination
);
return
0
;
}
static
int
show_entry
(
struct
tree_entry_list
*
e
,
int
level
,
char
*
pathbuf
)
int
main
(
int
argc
,
const
char
**
argv
)
{
int
err
=
0
;
if
(
e
!=
&
root_entry
)
{
int
pathlen
=
strlen
(
pathbuf
);
printf
(
"%06o %s %s "
,
e
->
mode
,
entry_type
(
e
),
entry_hex
(
e
));
write_name_quoted
(
pathbuf
,
pathlen
,
e
->
name
,
line_termination
,
stdout
);
putchar
(
line_termination
);
}
if
(
e
->
directory
)
{
/* If this is a directory, we have the following cases:
* (1) This is the top-level request (explicit path from the
* command line, or "root" if there is no command line).
* a. Without any flag. We show direct children. We do not
* recurse into them.
* b. With -r. We do recurse into children.
* c. With -d. We do not recurse into children.
* (2) We came here because our caller is either (1-a) or
* (1-b).
* a. Without any flag. We do not show our children (which
* are grandchildren for the original request).
* b. With -r. We continue to recurse into our children.
* c. With -d. We should not have come here to begin with.
*/
if
(
level
==
0
&&
!
(
ls_options
&
LS_TREE_ONLY
))
/* case (1)-a and (1)-b */
err
=
err
|
show_children
(
e
,
level
+
1
,
pathbuf
);
else
if
(
level
&&
ls_options
&
LS_RECURSIVE
)
/* case (2)-b */
err
=
err
|
show_children
(
e
,
level
+
1
,
pathbuf
);
}
return
err
;
}
static
int
list_one
(
const
char
*
path
)
{
int
err
=
0
;
char
pathbuf
[
MAXPATHLEN
+
1
];
struct
tree_entry_list
*
e
=
find_entry
(
path
,
pathbuf
);
if
(
!
e
)
{
/* traditionally ls-tree does not complain about
* missing path. We may change this later to match
* what "/bin/ls -a" does, which is to complain.
*/
return
err
;
}
err
=
err
|
show_entry
(
e
,
0
,
pathbuf
);
return
err
;
}
static
int
list
(
char
**
path
)
{
int
i
;
int
err
=
0
;
for
(
i
=
0
;
path
[
i
];
i
++
)
err
=
err
|
list_one
(
path
[
i
]);
return
err
;
}
static
const
char
ls_tree_usage
[]
=
"git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"
;
int
main
(
int
argc
,
char
**
argv
)
{
static
char
*
path0
[]
=
{
""
,
NULL
};
char
**
path
;
const
char
*
prefix
;
unsigned
char
sha1
[
20
];
char
*
buf
;
unsigned
long
size
;
prefix
=
setup_git_directory
();
while
(
1
<
argc
&&
argv
[
1
][
0
]
==
'-'
)
{
switch
(
argv
[
1
][
1
])
{
case
'z'
:
...
...
@@ -246,9 +84,11 @@ int main(int argc, char **argv)
if
(
get_sha1
(
argv
[
1
],
sha1
)
<
0
)
usage
(
ls_tree_usage
);
path
=
(
argc
==
2
)
?
path0
:
(
argv
+
2
);
prepare_root
(
sha1
);
if
(
list
(
path
)
<
0
)
die
(
"list failed"
);
pathspec
=
get_pathspec
(
prefix
,
argv
+
2
);
buf
=
read_object_with_reference
(
sha1
,
"tree"
,
&
size
,
NULL
);
if
(
!
buf
)
die
(
"not a tree object"
);
read_tree_recursive
(
buf
,
size
,
""
,
0
,
0
,
pathspec
,
show_tree
);
return
0
;
}
rev-list.c
浏览文件 @
5401f304
...
...
@@ -350,7 +350,8 @@ static int count_distance(struct commit_list *entry)
if
(
commit
->
object
.
flags
&
(
UNINTERESTING
|
COUNTED
))
break
;
nr
++
;
if
(
!
paths
||
(
commit
->
object
.
flags
&
TREECHANGE
))
nr
++
;
commit
->
object
.
flags
|=
COUNTED
;
p
=
commit
->
parents
;
entry
=
p
;
...
...
@@ -362,6 +363,7 @@ static int count_distance(struct commit_list *entry)
}
}
}
return
nr
;
}
...
...
@@ -382,15 +384,20 @@ static struct commit_list *find_bisection(struct commit_list *list)
nr
=
0
;
p
=
list
;
while
(
p
)
{
nr
++
;
if
(
!
paths
||
(
p
->
item
->
object
.
flags
&
TREECHANGE
))
nr
++
;
p
=
p
->
next
;
}
closest
=
0
;
best
=
list
;
p
=
list
;
while
(
p
)
{
int
distance
=
count_distance
(
p
);
for
(
p
=
list
;
p
;
p
=
p
->
next
)
{
int
distance
;
if
(
paths
&&
!
(
p
->
item
->
object
.
flags
&
TREECHANGE
))
continue
;
distance
=
count_distance
(
p
);
clear_distance
(
list
);
if
(
nr
-
distance
<
distance
)
distance
=
nr
-
distance
;
...
...
@@ -398,7 +405,6 @@ static struct commit_list *find_bisection(struct commit_list *list)
best
=
p
;
closest
=
distance
;
}
p
=
p
->
next
;
}
if
(
best
)
best
->
next
=
NULL
;
...
...
t/t0000-basic.sh
浏览文件 @
5401f304
...
...
@@ -126,19 +126,18 @@ test_expect_success \
'git-ls-tree output for a known tree.'
\
'diff current expected'
# This changed in ls-tree pathspec change -- recursive does
# not show tree nodes anymore.
test_expect_success
\
'showing tree with git-ls-tree -r'
\
'git-ls-tree -r $tree >current'
cat
>
expected
<<
\
EOF
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
EOF
...
...
t/t3100-ls-tree-restrict.sh
浏览文件 @
5401f304
...
...
@@ -54,8 +54,6 @@ test_expect_success \
cat >expected <<\EOF &&
100644 blob X path0
120000 blob X path1
040000 tree X path2
040000 tree X path2/baz
100644 blob X path2/baz/b
120000 blob X path2/bazbo
100644 blob X path2/foo
...
...
@@ -70,12 +68,14 @@ EOF
test_output'
# it used to be path1 and then path0, but with pathspec semantics
# they are shown in canonical order.
test_expect_success
\
'ls-tree filtered with path1 path0'
\
'git-ls-tree $tree path1 path0 >current &&
cat >expected <<\EOF &&
120000 blob X path1
100644 blob X path0
120000 blob X path1
EOF
test_output'
...
...
@@ -86,45 +86,34 @@ test_expect_success \
EOF
test_output'
# It used to show path2 and its immediate children but
# with pathspec semantics it shows only path2
test_expect_success
\
'ls-tree filtered with path2'
\
'git-ls-tree $tree path2 >current &&
cat >expected <<\EOF &&
040000 tree X path2
040000 tree X path2/baz
120000 blob X path2/bazbo
100644 blob X path2/foo
EOF
test_output'
test_expect_success
\
'ls-tree filtered with path2/baz'
\
'git-ls-tree $tree path2/baz >current &&
cat >expected <<\EOF &&
040000 tree X path2/baz
100644 blob X path2/baz/b
EOF
test_output'
# ... and path2/ shows the children.
test_expect_success
\
'ls-tree filtered with path2'
\
'git-ls-tree $tree path2 >current &&
'ls-tree filtered with path2
/
'
\
'git-ls-tree $tree path2
/
>current &&
cat >expected <<\EOF &&
040000 tree X path2
040000 tree X path2/baz
120000 blob X path2/bazbo
100644 blob X path2/foo
EOF
test_output'
# The same change -- exact match does not show children of
# path2/baz
test_expect_success
\
'ls-tree filtered with path2/'
\
'git-ls-tree $tree path2/ >current &&
'ls-tree filtered with path2/
baz
'
\
'git-ls-tree $tree path2/
baz
>current &&
cat >expected <<\EOF &&
040000 tree X path2
040000 tree X path2/baz
120000 blob X path2/bazbo
100644 blob X path2/foo
EOF
test_output'
...
...
t/t3101-ls-tree-dirname.sh
浏览文件 @
5401f304
...
...
@@ -59,24 +59,16 @@ test_expect_success \
EOF
test_output'
# Recursive does not show tree nodes anymore...
test_expect_success
\
'ls-tree recursive'
\
'git-ls-tree -r $tree >current &&
cat >expected <<\EOF &&
100644 blob X 1.txt
100644 blob X 2.txt
040000 tree X path0
040000 tree X path0/a
040000 tree X path0/a/b
040000 tree X path0/a/b/c
100644 blob X path0/a/b/c/1.txt
040000 tree X path1
040000 tree X path1/b
040000 tree X path1/b/c
100644 blob X path1/b/c/1.txt
040000 tree X path2
100644 blob X path2/1.txt
040000 tree X path3
100644 blob X path3/1.txt
100644 blob X path3/2.txt
EOF
...
...
@@ -110,41 +102,27 @@ test_expect_success \
EOF
test_output'
# I am not so sure about this one after ls-tree doing pathspec match.
# Having both path0/a and path0/a/b/c makes path0/a redundant, and
# it behaves as if path0/a/b/c, path1/b/c, path2 and path3 are specified.
test_expect_success
\
'ls-tree filter directories'
\
'git-ls-tree $tree path3 path2 path0/a/b/c path1/b/c path0/a >current &&
cat >expected <<\EOF &&
040000 tree X path3
100644 blob X path3/1.txt
100644 blob X path3/2.txt
040000 tree X path2
100644 blob X path2/1.txt
040000 tree X path0/a/b/c
100644 blob X path0/a/b/c/1.txt
040000 tree X path1/b/c
100644 blob X path1/b/c/1.txt
040000 tree X path0/a
040000 tree X path0/a/b
040000 tree X path2
040000 tree X path3
EOF
test_output'
# Again, duplicates are filtered away so this is equivalent to
# having 1.txt and path3
test_expect_success
\
'ls-tree filter odd names'
\
'git-ls-tree $tree 1.txt /1.txt //1.txt path3/1.txt /path3/1.txt //path3//1.txt path3 /path3/ path3// >current &&
cat >expected <<\EOF &&
100644 blob X 1.txt
100644 blob X 1.txt
100644 blob X 1.txt
100644 blob X path3/1.txt
100644 blob X path3/1.txt
100644 blob X path3/1.txt
040000 tree X path3
100644 blob X path3/1.txt
100644 blob X path3/2.txt
040000 tree X path3
100644 blob X path3/1.txt
100644 blob X path3/2.txt
040000 tree X path3
100644 blob X path3/1.txt
100644 blob X path3/2.txt
EOF
...
...
tree.c
浏览文件 @
5401f304
...
...
@@ -9,9 +9,16 @@ const char *tree_type = "tree";
static
int
read_one_entry
(
unsigned
char
*
sha1
,
const
char
*
base
,
int
baselen
,
const
char
*
pathname
,
unsigned
mode
,
int
stage
)
{
int
len
=
strlen
(
pathname
);
unsigned
int
size
=
cache_entry_size
(
baselen
+
len
);
struct
cache_entry
*
ce
=
xmalloc
(
size
);
int
len
;
unsigned
int
size
;
struct
cache_entry
*
ce
;
if
(
S_ISDIR
(
mode
))
return
READ_TREE_RECURSIVE
;
len
=
strlen
(
pathname
);
size
=
cache_entry_size
(
baselen
+
len
);
ce
=
xmalloc
(
size
);
memset
(
ce
,
0
,
size
);
...
...
@@ -67,9 +74,10 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
return
0
;
}
static
int
read_tree_recursive
(
void
*
buffer
,
unsigned
long
size
,
const
char
*
base
,
int
baselen
,
int
stage
,
const
char
**
match
)
int
read_tree_recursive
(
void
*
buffer
,
unsigned
long
size
,
const
char
*
base
,
int
baselen
,
int
stage
,
const
char
**
match
,
read_tree_fn_t
fn
)
{
while
(
size
)
{
int
len
=
strlen
(
buffer
)
+
1
;
...
...
@@ -86,6 +94,14 @@ static int read_tree_recursive(void *buffer, unsigned long size,
if
(
!
match_tree_entry
(
base
,
baselen
,
path
,
mode
,
match
))
continue
;
switch
(
fn
(
sha1
,
base
,
baselen
,
path
,
mode
,
stage
))
{
case
0
:
continue
;
case
READ_TREE_RECURSIVE
:
break
;;
default:
return
-
1
;
}
if
(
S_ISDIR
(
mode
))
{
int
retval
;
int
pathlen
=
strlen
(
path
);
...
...
@@ -106,22 +122,20 @@ static int read_tree_recursive(void *buffer, unsigned long size,
retval
=
read_tree_recursive
(
eltbuf
,
eltsize
,
newbase
,
baselen
+
pathlen
+
1
,
stage
,
match
);
stage
,
match
,
fn
);
free
(
eltbuf
);
free
(
newbase
);
if
(
retval
)
return
-
1
;
continue
;
}
if
(
read_one_entry
(
sha1
,
base
,
baselen
,
path
,
mode
,
stage
)
<
0
)
return
-
1
;
}
return
0
;
}
int
read_tree
(
void
*
buffer
,
unsigned
long
size
,
int
stage
,
const
char
**
match
)
{
return
read_tree_recursive
(
buffer
,
size
,
""
,
0
,
stage
,
match
);
return
read_tree_recursive
(
buffer
,
size
,
""
,
0
,
stage
,
match
,
read_one_entry
);
}
struct
tree
*
lookup_tree
(
const
unsigned
char
*
sha1
)
...
...
tree.h
浏览文件 @
5401f304
...
...
@@ -35,4 +35,13 @@ int parse_tree(struct tree *tree);
/* Parses and returns the tree in the given ent, chasing tags and commits. */
struct
tree
*
parse_tree_indirect
(
const
unsigned
char
*
sha1
);
#define READ_TREE_RECURSIVE 1
typedef
int
(
*
read_tree_fn_t
)(
unsigned
char
*
,
const
char
*
,
int
,
const
char
*
,
unsigned
int
,
int
);
extern
int
read_tree_recursive
(
void
*
buffer
,
unsigned
long
size
,
const
char
*
base
,
int
baselen
,
int
stage
,
const
char
**
match
,
read_tree_fn_t
fn
);
#endif
/* TREE_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录