repo系列之repo-diffmanifests源码分析
repo diffmanifests 子命令源码分析
这个命令的作用是比较2个 manifest xml 文件的差异的,比较里面每个仓库的git log差异,
一般用来对比2个构建版本之间的提交差异,生成 changelog 使用的。
效果如下:
1 | repo diffmanifests old.xml new.xml |
使用的 repo init 命令如下:
1 | repo init --repo-url https://gitee.com/mamh-mixed/git-repo --repo-branch stable-v1.13.2 --reference /home/mirror \ |
使用的repo 版本是 v1.13.2
从 diffmanifests old.xml new.xml 执行开始说起
1. Execute() 方法入口
1 | def Execute(self, opt, args): |
此时 opt, args 2个参数值如下:
1 | args = {list: 2} ['old.xml', 'new.xml'] |
2. self.out 的初始化
1 | self.out = _Coloring(self.manifest.globalConfig) |
class _Coloring 是 继承了 class Coloring。这个类来自 color.py 文件里面
1 | class Coloring(object): |
在实例化 _Coloring 类的时候,传入了一个 self.manifest.globalConfig,他是一个 GitConfig 对象(来自 git_config.py 文件中的 class GitConfig(object)),如下:
1 | globalConfig = {GitConfig} <git_config.GitConfig object at 0x7f68e172dc10> |
这个 self.manifest 成员变量是在什么时候初始化的呢? 在class Diffmanifests(PagedCommand)
里面都没有找到,在她的父类里面也没找到,
最后发现是在 main.py 文件中的class _Repo(object):
里面进行的初始化 cmd.manifest = XmlManifest(cmd.repodir)
实例化 _Coloring 的时候 第一个参数是
self.manifest.globalConfig
,在
_Coloring
的__init__
方法里面会调用 父类 Coloring 的__init__
方法, 第二个参数是固定死的"status"
最终效果就是 self.out 是一个
Coloring
类的实例,第一个参数是self.manifest.globalConfig
,第二个参数是"status"
。a. 这个参数
"status"
会拼接'color.%s' % section_type
得到color.status
, 这个是git config
里面可能会配置的一项.b. 查看
git config
的说明:1
2
3
4color.status
A boolean to enable/disable color in the output of git-status(1). May be set to always, false (or never) or
auto (or true), in which case colors are used only when the output is to a terminal. If unset, then the value
of color.ui is used (auto by default).这2个参数有什么作用,展开说明一下这个
class Coloring
类中的__init__
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Coloring(object):
def __init__(self, config, section_type):
self._section = 'color.%s' % section_type
self._config = config
self._out = sys.stdout
on = DEFAULT
if on is None:
on = self._config.GetString(self._section)
if on is None:
on = self._config.GetString('color.ui')
if on == 'auto':
if pager.active or os.isatty(1):
self._on = True
else:
self._on = False
elif on in ('true', 'always'):
self._on = True
else:
self._on = Falsea.
self._section
就被赋值为color.status
了。self._config
就是GitConfig
实例对象。self._out
是sys.stdout
。
b. 继续往下面的一段代码就是初始化self._on
了。初始 on 被赋值一个 全局的 DEFAULT。 经过一系列判断,这个 on 会被赋值给self._on
。
初始化 on 的时候可以看到 先去 获取color.status
有没有配置,没有会去使用color.ui
。
c. 如果 on 是auto
的情况,会判断pager.active or os.isatty(1)
, 如果是真,那么 最终 self._on 被赋值 True了。
d. 如果 on 是'true', 'always'
那么 最终self._on
被赋值 True了。其他情况 self._on 会被设置为 False。
e. 这个self._on
其实会决定后面的打印输出会不会带上颜色。self.out 的作用
1
self.out.nl()
1
2def nl(self):
self._out.write('\n')主要作用就是打印换行
2. self.printText 的初始化
1 | self.printText = self.out.nofmt_printer('text') |
通过 self.out 调用 nofmt_printer(‘text’) 方法,返回的是一个 method的。
1
2
3
4
5
6
7def nofmt_printer(self, opt=None, fg=None, bg=None, attr=None):
s = self
c = self.nofmt_colorer(opt, fg, bg, attr)
def f(fmt):
s._out.write(c(fmt))
return f改方法返回了一个
def f(fmt):
方法,这个 f 方法里面就是调用了s._out.write()
效果就是sys.stdout.write()
write()
方法里面的参数是会经过c(fmt)
包装一下的,c 这个也是一个方法,是通过self.nofmt_colorer(opt, fg, bg, attr)
包装出来的一个方法1
2
3
4
5
6
7
8
9
10
11def nofmt_colorer(self, opt=None, fg=None, bg=None, attr=None):
if self._on:
c = self._parse(opt, fg, bg, attr)
def f(fmt):
return ''.join([c, fmt, RESET])
return f
else:
def f(fmt):
return fmt
return f这个nofmt_colorer方法比较绕,发主要就是返回另外一个方法,赋值给 c 变量使用,
c(fmt)
经过这样去调用,把需要打印的字符串fmt包装一下,返回一个新的格式的字符串fmt
。a. 如果
self._on
是 False 的情况,返回一个1
2def f(fmt):
return fmt这样的方法,这个时候 其实是什么都没有做,这样经过
c(fmt)
调用,返回的还是原来的fmt
的内容。b. 如果 如果
self._on
是 True 的情况,返回一个1
2
3
4
5c = self._parse(opt, fg, bg, attr)
def f(fmt):
return ''.join([c, fmt, RESET])
return f这样的方法,这个时候,这样经过
c(fmt)
调用,返回的是''.join([c, fmt, RESET])
, 其实就是在fmt的前后加上了一个 c 和一个 RESET。c. c 是什么东东呢? c 是
self._parse(opt, fg, bg, attr)
调用后返回的一个值。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25def _parse(self, opt, fg, bg, attr):
if not opt:
return _Color(fg, bg, attr)
v = self._config.GetString('%s.%s' % (self._section, opt))
if v is None:
return _Color(fg, bg, attr)
v = v.strip().lower()
if v == "reset":
return RESET
elif v == '':
return _Color(fg, bg, attr)
have_fg = False
for a in v.split(' '):
if is_color(a):
if have_fg:
bg = a
else:
fg = a
elif is_attr(a):
attr = a
return _Color(fg, bg, attr)这个
self._parse(opt, fg, bg, attr)
也是经过一系列判断,最终返回_Color(fg, bg, attr)
方法调用的返回值。
它有有三个参数,fg 表示前景颜色, bg表示背景颜色,attr 表示属性。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36def _Color(fg=None, bg=None, attr=None):
fg = COLORS[fg]
bg = COLORS[bg]
attr = ATTRS[attr]
if attr >= 0 or fg >= 0 or bg >= 0:
need_sep = False
code = "\033["
if attr >= 0:
code += chr(ord('0') + attr)
need_sep = True
if fg >= 0:
if need_sep:
code += ';'
need_sep = True
if fg < 8:
code += '3%c' % (ord('0') + fg)
else:
code += '38;5;%d' % fg
if bg >= 0:
if need_sep:
code += ';'
if bg < 8:
code += '4%c' % (ord('0') + bg)
else:
code += '48;5;%d' % bg
code += 'm'
else:
code = ''
return code其实也是经过一系列判断,返回一串字符串的。
_Color("red","blue","dim")
这样调用 返回一个'\033[2;31;44m'
这样的字符串,它表示的就是蓝色背景红色字体的。d. RESET 是什么东东呢?RESET是一个写死的值:
RESET = "\033[m"
. 这个值是终端上打印彩色的时候重置颜色的一个特殊的值。e. 这里在初始化
self.printText
的时候是没有传递fg=None, bg=None, attr=None
三个参数的。其实最终的效果self.printText()
就是sys.out.write()
的调用效果f. opt 这个参数的作用,是要和
color.status
进行拼接的。color.status.text
。 这个可以配置reset
和配置颜色normal black red green yellow blue magenta cyan white
或者是属性bold dim ul blink reverse
1
2
3
4
5$ head ~/.gitconfig
[color]
ui = true
[color "status"]
text = reset如果这个配置文件里面这样配置了
如果
self._config.GetString("color.ui")
这样调用会,得到 ~/.gitconfig 中的 true。如果
self._config.GetString("color.ui.text")
这样调用会,得到 ~/.gitconfig 中的 reset。如果
text = reset
, 经过self._parse(opt, fg, bg, attr)
调用后返回的是RESET = "\033[m"
这个值。另外一种配置方式就是3个值分别表示 fg,bg,attr,例如
text = black red blod
这里的 have_fg 变量没有被再次赋值呀,是有bug的呀。。。。作者的意思应该是先判断fg是否被赋值了,赋值过之后第二个颜色应该是要给到bg上了。
3. 其他几个 print 方法的初始化
1 | if opt.color: |
- 如果命令行上有 –no-color 会影响到 opt.color 的值。默认这个是True的。
- 这几个方法的初始化和上面
self.printText
都比较类似,无非就是传递给nofmt_printer(self, opt=None, fg=None, bg=None, attr=None)
方法的参数值不一样。 - 从中可以发现
gitconfig
下面的color.status
下面还可以 配置'project' 'green' 'red' 'revision'
1
2
3
4
5
6
7
8
9$ head ~/.gitconfig
[color]
ui = true
[color "status"]
text = black red dim # 这个会影响` changed projects` `removed projects` `added projects` 这3行的颜色。其实不单单颜色还有样式的,例如粗体字,下划线,闪烁
project = black red dim # 这个控制仓库名称的显示的颜色的。
green = black red dim # 这个控制[+] 和 [-] 这个方括号这一段的颜色的。默认是加号绿色的。
red = black red dim # 这个控制[+] 和 [-] 这个方括号这一段的颜色的。默认是减号红色的。
revision = black red dim # 控制 from to 之间的 revision 的颜色的。 - 默认情况下:仓库名称, revision, 加 减 号 都是会有颜色样式显示的。 如果命令行上带 –no-color 的时候:这几个都会是
self.printText
。 - 如果带命令行上带 –no-color 的时候, 并且 text 选项没有设置的化,是不会显示颜色的,但是输出的文本内容中会有 RESET 这个特殊字符。这里的行为感觉也有点小bug。
如果要解析这样的命令输出的化要特别注意。 可以在repo后面带上–color=never这样全局的禁用颜色样式和特殊字符了。
4. XmlManifest 的初始化
1 | manifest1 = XmlManifest(self.manifest.repodir) |
这一段代码会初始化2个 XmlManifest 类的实例, 命令行参数会带上2个xml文件名,默认第一个的xml文件会和manifest1实例绑定。
如果没有第二个会使用 .repo/manifest.xml 这个xml文件和manifest2实例绑定。如果有第二个xml参数,那么就第2个的xml文件会和manifest2实例绑定。
1
2
3args = {list: 2} ['old.xml', 'new.xml']
0 = {str} 'old.xml'
1 = {str} 'new.xml'我们测试的命令行参数是带的2个xml文件名的。
self.manifest.repodir 这个路径就是 .repo/ 这个路径,转换过的一个绝对路径。
4. 对比2个xml获取差异信息
其实就是对比2个xml里面的各个仓库的git log的差异。最终的调用的命令就是git log oldRev..newRev
1 | diff = manifest1.projectsDiff(manifest2) |
4.1 projectsDiff() 方法
1 | def projectsDiff(self, manifest): |
这个方法在manifest_xml.py文件里面
首先是获取了两个 paths 相关的信息
1
2
3
4
5
6
7
8
9
10fromProjects = self.paths # 获取第1个manifest xml里面的project信息
toProjects = manifest.paths # 获取第2个manifest xml里面的project信息
fromKeys = sorted(fromProjects.keys()) # 对字典的key进行排序
toKeys = sorted(toProjects.keys())
@property
def paths(self):
self._Load()
return self._paths1
2
3fromProjects = {dict: 2} {u'git-repo': <project.Project object at 0x7efce8971a90>, u'git-repo-go': <project.Project object at 0x7efce8971c50>}
u'git-repo' = {Project} <project.Project object at 0x7efce8971a90>
u'git-repo-go' = {Project} <project.Project object at 0x7efce8971c50>是一个字典,其实就是解析manifest xml得到里面的所有的project相关的信息。以path作为字典的key了。
定义一个 diff 字典,后续用来存放差异信息的
1
diff = {'added': [], 'removed': [], 'changed': [], 'unreachable': []}
这个对比其实就是2个集合关系的比较。集合的交集,补集等。
added为新增的仓库,removed是删除的仓库,这2种就是2个集合的补集。
changed的就是集合的交集的仓库。
unreachable 表示不可达的仓库,revision是不在这个仓库里面的。
开始循环fromKeys这个集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15for proj in fromKeys:
if not proj in toKeys:
diff['removed'].append(fromProjects[proj])
else:
fromProj = fromProjects[proj]
toProj = toProjects[proj]
try:
fromRevId = fromProj.GetCommitRevisionId()
toRevId = toProj.GetCommitRevisionId()
except ManifestInvalidRevisionError:
diff['unreachable'].append((fromProj, toProj))
else:
if fromRevId != toRevId:
diff['changed'].append((fromProj, toProj))
toKeys.remove(proj)a. 开始这里 判断 不在 toKeys 集合里面的仓库就是被移除删除的情况
1
2
3for proj in fromKeys: # from 是旧的,是左边, to是新的,是右边。 遍历旧的集合,发现不在新的集合里面的那就是删除的情况。直接是追加到` diff['removed'] `对应的列表里面。
if not proj in toKeys:
diff['removed'].append(fromProjects[proj])b. 交集的情况,就是 from 和 to 两个集合都存在的仓库
1
2
3
4
5
6
7
8
9
10
11
12else:
fromProj = fromProjects[proj]
toProj = toProjects[proj]
try:
fromRevId = fromProj.GetCommitRevisionId()
toRevId = toProj.GetCommitRevisionId()
except ManifestInvalidRevisionError:
diff['unreachable'].append((fromProj, toProj))
else:
if fromRevId != toRevId:
diff['changed'].append((fromProj, toProj))
toKeys.remove(proj)分别获取from的仓库和to的仓库,然后分别获取到对应的revision id值,保存在 fromRevId 和 toRevId 两个变量里面。
只有 fromRevId 和 toRevId 不相等的情况,才会把这2个revision id值追加到
diff['changed']
对应的列表里面。如果这2个revid是相等说明这个仓库没有改变,说明提交历史是一致的。在最后还需要
toKeys.remove(proj)
把它从右边to那个集合里面删除掉。这个是为 后面判断diff['added']
的情况做准备的。c. 最后处理新增的仓库的情况, 把 to 那个集合里面剩下的遍历一遍就是了。因为上面在循环的过程中把 相同仓库的情况已经从 to 集合里面删除掉了。所以剩下的没有被处理的就是新增的仓库了。
1
2for proj in toKeys: # toKeys 集合只是path,这里是把对应的 project获取到,追加到列表里面。
diff['added'].append(toProjects[proj])
5. 打印差异信息
1 | if opt.raw: |
- 命令行上的
--raw
选项会影响opt.raw
的值,默认是false的,带上这个选项才会变成True的。其实就是最终的打印格式不太一样带上1
2
3
4
5
6
7
8
9
10
11repo diffmanifests old.xml new.xml --raw
A manifest 372366704d46173df5b0ba6e5887beb6a8d0cbec
R git-repo-go 8de1b394acad3db7c6b0b691be045f897082fdce
C git-repo 13f323b2c221db4e69e3f5a671455954b65f1fb3 3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be
R 13f323b event_log: turn id generation from a generator to a func call
R 12ee544 init: Remove -c short option for --current-branch
R e158e38 Merge "README: link in new bug tracker"
R d4b13c2 Leverage the next keyword from python 2.7--raw
的效果如上。 很类似git status --short
那样的。
5.1 调用 _printRawDiff 打印差异信息
1 | def _printRawDiff(self, diff): |
里面是按照那个 diff 字典来打印的,先处理
diff['added']
的情况,然后是diff['removed']
, 再次diff['changed']
, 最后是diff['unreachable']
打印新增仓库的情况 和 删除仓库的情况,这2个情况是一样的。
a. 循环遍历即可,打印
"A"
或者是"R"
,仓库路径, revision ID。打印一个换行\n
b. 这里的
self.printText
方法就是上面讲过的 通过self.out.nofmt_printer('text')
获取的,其实最终效果就是 调用的sys.out.write()
方法c. 效果如下
1
2A manifest 372366704d46173df5b0ba6e5887beb6a8d0cbec
R git-repo-go 8de1b394acad3db7c6b0b691be045f897082fdce打印共有的仓库的情况。
a. 循环遍历。 打印
"C"
,打印仓库路径,打印左侧的revisionID,打印右侧的revisionID,打印换行符。b. 调用
self._printLogs(project, otherProject, raw=True, color=False)
打印2个revID之间的git log的差异信息。后面再展开这个方法。 这里会打印R开头的或者A开头的。其实和另外一种打印格式中的[+]
[-]
相对应了。c. 效果如下
1
2
3
4
5
6C git-repo 13f323b2c221db4e69e3f5a671455954b65f1fb3 3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be
R 13f323b event_log: turn id generation from a generator to a func call
R 12ee544 init: Remove -c short option for --current-branch
R e158e38 Merge "README: link in new bug tracker"
R d4b13c2 Leverage the next keyword from python 2.7打印 unreachable 的情况。
a. 循环遍历即可,打印
"U %s %s %s", 仓库路径,左侧revision ID, 右侧revision ID
。 打印一个换行符。b 效果如下
1
U git-repo xxxxxx 13f323b2c221db4e69e3f5a671455954b65f1fb3
add的情况打印是带 A 开头的。 removed的情况是打印的 R 开头的。unreachable 的情况是打印的 U 开头的。
5.2 调用 _printDiff 打印差异信息
1 | def _printDiff(self, diff, color=True, pretty_format=None): |
和上面的一样。里面是按照那个 diff 字典来打印的,先处理
diff['added']
的情况,然后是diff['removed']
, 再次diff['changed']
, 最后是diff['unreachable']
打印新增仓库的情况 和 删除仓库的情况,这2个情况是一样的。
1
2
3
4
5
6
7
8
9self.out.nl()
self.printText('added projects : \n')
self.out.nl()
for project in diff['added']:
self.printProject('\t%s' % (project.relpath))
self.printText(' at revision ')
self.printRevision(project.revisionExpr)
self.out.nl()a. 先打印换行,然后打印
'added projects : \n'
或者是'removed projects : \n'
。打印仓库路径。打印' at revision '
。打印 revision id。b.
self.printProject
和self.printRevision
是2个方法,和self.printText
是类似的。c. 上面合起来打印的效果如下所示:
1
2
3
4
5
6
7
8added projects :
manifest at revision 372366704d46173df5b0ba6e5887beb6a8d0cbec
removed projects :
git-repo-go at revision 8de1b394acad3db7c6b0b691be045f897082fdce打印共有的仓库的情况。
1
2
3
4
5
6
7
8
9
10
11
12
13self.out.nl()
self.printText('changed projects : \n')
self.out.nl()
for project, otherProject in diff['changed']:
self.printProject('\t%s' % (project.relpath))
self.printText(' changed from ')
self.printRevision(project.revisionExpr)
self.printText(' to ')
self.printRevision(otherProject.revisionExpr)
self.out.nl()
self._printLogs(project, otherProject, raw=False, color=color,
pretty_format=pretty_format)a. 先是打印换行和 ‘changed projects : \n’
b. 循环打印, 每一个仓库会按如下内容打印:制表符, 仓库路径,
' changed from '
, 左侧revision id,' to '
, 右侧的 revision id, 换行效果如下:
1
git-repo changed from 3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be to 13f323b2c221db4e69e3f5a671455954b65f1fb3
c. 然后调用 self._printLogs 方法打印2个reivison id 直接的git log的差异信息。
效果如下:每一行前面都有2个制表符,起到缩进的效果。1
2
3
4
5[+] 13f323b event_log: turn id generation from a generator to a func call
[+] 12ee544 init: Remove -c short option for --current-branch
[+] e158e38 Merge "README: link in new bug tracker"
[+] d4b13c2 Leverage the next keyword from python 2.7
打印 unreachable 的情况。
1
2
3
4
5
6
7
8
9
10self.out.nl()
self.printText('projects with unreachable revisions : \n')
self.out.nl()
for project, otherProject in diff['unreachable']:
self.printProject('\t%s ' % (project.relpath))
self.printRevision(project.revisionExpr)
self.printText(' or ')
self.printRevision(otherProject.revisionExpr)
self.printText(' not found')
self.out.nl()a. 和上面的打印类似。先打印换行,然后打印
'projects with unreachable revisions : \n'
b. 循环打印, 每一个仓库会按如下内容打印:制表符, 仓库路径, 左侧仓库的revision id,
'or'
, 左侧仓库的revision id,' not found'
, 换行。c.效果如下:
1
2
3projects with unreachable revisions :
git-repo 8de1b394acad3db7c6b0b691be045f897082fdce or 13f323b2c221db4e69e3f5a671455954b65f1fb3 not found
5.3 调用 _printLogs 打印git log 差异信息
1 | def _printLogs(self, project, otherProject, raw=False, color=True, pretty_format=None): |
上面是先获取 logs 信息,然后按换行符截取之后循环打印。
参数 project 是左侧仓库相关信息的一个对象。也可以理解为旧的manifest xml里面的仓库。
参数 otherProject 是右侧仓库相关信息的一个对象。也可以理解为新的manifest xml里面的仓库。
参数 raw 是 True 或者是 False,这个是可以根据 命令行上 是否带 –raw 选项来决定。默认是False的。
参数 color 是 True 或者是 False,这个是可以根据 命令行上 是否带 –no-color 选项来决定。默认是True的。
参数pretty_format是命令行上 是否带 –pretty-format
1 | if logs['removed']: |
1 | if logs['added']: |
这个方法里面最后打印的时候分了2个情况,一个是打印
logs['removed']
里面的,一个是打印logs['added']
。 这里就是 对应了[+]
和[-]
加号和减号的情况logs['removed']
和logs['added']
就是git log --oneline
的输出。 每一行是一个 revisoinid 然后跟着这次提交的 subject。是 raw 的情况直接打印 一个
' R '
然后紧接着是 revisoinid 和 subject了。最后打印一个换行。非 raw 的情况 打印 一个
'\t\t[-] '
或者是'\t\t[+] '
然后紧接着是 revisoinid 和 subject了。最后打印一个换行。self.printAdded 和 self.printRemoved 是前面提交到的一个打印方法,可以打印带有颜色字的输出。
self.printText 一般可以认为的打印没有颜色的输出的。简单的可以这样理解。
5.4 调用 getAddedAndRemovedLogs 获取git log 差异信息
1 | def getAddedAndRemovedLogs(self, toProject, oneline=False, color=True, pretty_format=None): |
- 首先是 获取旧仓库的revID,然后获取新仓库的revID.
1
2selfId = {unicode} u'3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be' 这个表示旧的
toId = {unicode} u'13f323b2c221db4e69e3f5a671455954b65f1fb3' 这个表示新的 - 然后调用self._getLogs方法,调用2次,分别是 新旧revision ID 交换顺序调用。一种存放到
logs['added']
。 一种存放到logs['removed']
。 其实效果是一样的。
1 | def _getLogs(self, rev1, rev2, oneline=False, color=True, pretty_format=None): |
举例这里调用:参数 rev1 = u’3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be’ 参数 rev2 = u’13f323b2c221db4e69e3f5a671455954b65f1fb3’。oneline = True。 color=True 。pretty_format=None
最终会调用
git log --oneline
这个命令来生成git log差异信息的。['log', u'3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be..13f323b2c221db4e69e3f5a671455954b65f1fb3', '--color', '--oneline']
最终就是执行
git log 3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be..13f323b2c221db4e69e3f5a671455954b65f1fb3 --color --oneline
输出如下:
1
2
3
413f323b event_log: turn id generation from a generator to a func call
12ee544 init: Remove -c short option for --current-branch
e158e38 Merge "README: link in new bug tracker"
d4b13c2 Leverage the next keyword from python 2.7这个命令直接终端上执行是会带
(HEAD -> default, tag: v1.13.2, origin/stable-v1.13.2, origin/stable, gitee/stable-v1.13.2)
这些信息的,1
2
3
4
5git log 3bbbcaf99d6137b3ca88dd8bb0acc8733cf1e6be..13f323b2c221db4e69e3f5a671455954b65f1fb3 --color --oneline
13f323b (HEAD -> default, tag: v1.13.2, origin/stable-v1.13.2, origin/stable, gitee/stable-v1.13.2) event_log: turn id generation from a generator to a func call
12ee544 (tag: v1.13.1, origin/bs_stable, origin/bs_master) init: Remove -c short option for --current-branch
e158e38 Merge "README: link in new bug tracker"
d4b13c2 Leverage the next keyword from python 2.7但是repo代码里面执行是没有的。感觉是 默认带上了
--no-decorate
选项的效果。查看git log帮助手册看到如下描述:
1
2
3
4
5--no-decorate, --decorate[=short|full|auto|no]
Print out the ref names of any commits that are shown. If short is specified, the ref name prefixes refs/heads/,
refs/tags/ and refs/remotes/ will not be printed. If full is specified, the full ref name (including prefix) will
be printed. If auto is specified, then if the output is going to a terminal, the ref names are shown as if short
were given, otherwise no ref names are shown. The default option is short.如果是输出到终端默认是short的效果。
执行到
log = GitCommand(self, cmd, capture_stdout=True, capture_stderr=True)
这里 就是 调用了subprocess.Popen
去调用外部git
命令了。