chiark / gitweb /
39c21182f6f5a3ab099d761eee0df6a5dec1b169
[stgit] / stgit / commands / log.py
1 __copyright__ = """
2 Copyright (C) 2006, Catalin Marinas <catalin.marinas@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License version 2 as
6 published by the Free Software Foundation.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 """
17
18 import sys, os, time
19 from optparse import OptionParser, make_option
20 from pydoc import pager
21 from stgit.commands.common import *
22 from stgit import stack, git
23 from stgit.out import *
24
25 help = 'display the patch changelog'
26 usage = """%prog [options] [patch]
27
28 List all the current and past commit ids of the given patch. The
29 --graphical option invokes gitk instead of printing. The changelog
30 commit messages have the form '<action> <new-patch-id>'. The <action>
31 can be one of the following:
32
33   new     - new patch created
34   refresh - local changes were added to the patch
35   push    - the patch was cleanly pushed onto the stack
36   push(m) - the patch was pushed onto the stack with a three-way merge
37   push(f) - the patch was fast-forwarded
38   undo    - the patch boundaries were restored to the old values
39
40 Note that only the diffs shown in the 'refresh', 'undo' and 'sync'
41 actions are meaningful for the patch changes. The 'push' actions
42 represent the changes to the entire base of the current
43 patch. Conflicts reset the patch content and a subsequent 'refresh'
44 will show the entire patch."""
45
46 directory = DirectoryHasRepository()
47 options = [make_option('-b', '--branch',
48                        help = 'use BRANCH instead of the default one'),
49            make_option('-p', '--patch',
50                        help = 'show the refresh diffs',
51                        action = 'store_true'),
52            make_option('-n', '--number', type = 'int',
53                        help = 'limit the output to NUMBER commits'),
54            make_option('-f', '--full',
55                        help = 'show the full commit ids',
56                        action = 'store_true'),
57            make_option('-g', '--graphical',
58                        help = 'run gitk instead of printing',
59                        action = 'store_true')]
60
61 def show_log(log, options):
62     """List the patch changelog
63     """
64     commit = git.get_commit(log)
65     if options.number != None:
66         n = options.number
67     else:
68         n = -1
69     diff_list = []
70     while commit:
71         if n == 0:
72             # limit the output
73             break
74
75         log = commit.get_log().split('\n')
76
77         cmd_rev = log[0].split()
78         if len(cmd_rev) >= 2:
79             cmd = cmd_rev[0]
80             rev = cmd_rev[1]
81         elif len(cmd_rev) == 1:
82             cmd = cmd_rev[0]
83             rev = ''
84         else:
85             cmd = rev = ''
86
87         if options.patch:
88             if cmd in ['refresh', 'undo', 'sync', 'edit']:
89                 diff_list.append(git.pretty_commit(commit.get_id_hash()))
90
91                 # limiter decrement
92                 n -= 1
93         else:
94             if len(log) >= 3:
95                 notes = log[2]
96             else:
97                 notes = ''
98             author_name, author_email, author_date = \
99                          name_email_date(commit.get_author())
100             secs, tz = author_date.split()
101             date = '%s %s' % (time.ctime(int(secs)), tz)
102
103             if options.full:
104                 out.stdout('%-7s %-40s %s' % (cmd[:7], rev[:40], date))
105             else:
106                 out.stdout('%-8s [%-7s] %-28s  %s' % \
107                            (rev[:8], cmd[:7], notes[:28], date))
108
109             # limiter decrement
110             n -= 1
111
112         parent = commit.get_parent()
113         if parent:
114             commit = git.get_commit(parent)
115         else:
116             commit = None
117
118     if options.patch and diff_list:
119         pager('\n'.join(diff_list).rstrip())
120
121 def func(parser, options, args):
122     """Show the patch changelog
123     """
124     if len(args) == 0:
125         name = crt_series.get_current()
126         if not name:
127             raise CmdException, 'No patches applied'
128     elif len(args) == 1:
129         name = args[0]
130         if not name in crt_series.get_applied() + crt_series.get_unapplied() + \
131                crt_series.get_hidden():
132             raise CmdException, 'Unknown patch "%s"' % name
133     else:
134         parser.error('incorrect number of arguments')
135
136     patch = crt_series.get_patch(name)
137
138     log = patch.get_log()
139     if not log:
140         raise CmdException, 'No changelog for patch "%s"' % name
141
142     if options.graphical:
143         if os.system('gitk %s' % log) != 0:
144             raise CmdException, 'gitk execution failed'
145     else:
146         show_log(log, options)