Allow specifying path to 'dulwich log'.
[jelmer/dulwich.git] / bin / dulwich
1 #!/usr/bin/python
2 # dul-daemon - Simple git smart server client
3 # Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
4
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
8 # or (at your option) a later version of the License.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA  02110-1301, USA.
19
20 import sys
21 from getopt import getopt
22
23 def get_transport_and_path(uri):
24     from dulwich.client import TCPGitClient, SSHGitClient, SubprocessGitClient
25     for handler, transport in (("git://", TCPGitClient), ("git+ssh://", SSHGitClient)):
26         if uri.startswith(handler):
27             host, path = uri[len(handler):].split("/", 1)
28             return transport(host), "/"+path
29     # if its not git or git+ssh, try a local url..
30     return SubprocessGitClient(), uri
31
32
33 def cmd_fetch_pack(args):
34     from dulwich.repo import Repo
35     opts, args = getopt(args, "", ["all"])
36     opts = dict(opts)
37     client, path = get_transport_and_path(args.pop(0))
38     r = Repo(".")
39     if "--all" in opts:
40         determine_wants = r.object_store.determine_wants_all
41     else:
42         determine_wants = lambda x: [y for y in args if not y in r.object_store]
43     graphwalker = r.get_graph_walker()
44     client.fetch(path, r.object_store, determine_wants)
45
46
47 def cmd_log(args):
48     from dulwich.repo import Repo
49     opts, args = getopt(args, "", [])
50     if len(args) > 0:
51         path = args.pop(0)
52     else:
53         path = "."
54     r = Repo(path)
55     todo = [r.head()]
56     done = set()
57     while todo:
58         sha = todo.pop()
59         assert isinstance(sha, str)
60         if sha in done:
61             continue
62         done.add(sha)
63         commit = r.commit(sha)
64         print "-" * 50
65         print "commit: %s" % sha
66         if len(commit.parents) > 1:
67             print "merge: %s" % "...".join(commit.parents[1:])
68         print "author: %s" % commit.author
69         print "committer: %s" % commit.committer
70         print ""
71         print commit.message
72         print ""
73         todo.extend([p for p in commit.parents if p not in done])
74
75
76 def cmd_dump_pack(args):
77     from dulwich.errors import ApplyDeltaError
78     from dulwich.pack import Pack, sha_to_hex
79     import os
80     import sys
81
82     opts, args = getopt(args, "", [])
83
84     if args == []:
85         print "Usage: dulwich dump-pack FILENAME"
86         sys.exit(1)
87
88     basename, _ = os.path.splitext(args[0])
89     x = Pack(basename)
90     print "Object names checksum: %s" % x.name()
91     print "Checksum: %s" % sha_to_hex(x.get_stored_checksum())
92     if not x.check():
93         print "CHECKSUM DOES NOT MATCH"
94     print "Length: %d" % len(x)
95     for name in x:
96         try:
97             print "\t%s" % x[name]
98         except KeyError, k:
99             print "\t%s: Unable to resolve base %s" % (name, k)
100         except ApplyDeltaError, e:
101             print "\t%s: Unable to apply delta: %r" % (name, e)
102
103
104 def cmd_dump_index(args):
105     from dulwich.index import Index
106
107     opts, args = getopt(args, "", [])
108
109     if args == []:
110         print "Usage: dulwich dump-index FILENAME"
111         sys.exit(1)
112
113     filename = args[0]
114     idx = Index(filename)
115
116     for o in idx:
117         print o, idx[o]
118
119
120 def cmd_init(args):
121     from dulwich.repo import Repo
122     import os
123     opts, args = getopt(args, "", ["--bare"])
124     opts = dict(opts)
125
126     if args == []:
127         path = os.getcwd()
128     else:
129         path = args[0]
130
131     if not os.path.exists(path):
132         os.mkdir(path)
133
134     if "--bare" in opts:
135         Repo.init_bare(path)
136     else:
137         Repo.init(path)
138
139
140 def cmd_clone(args):
141     from dulwich.repo import Repo
142     import os
143     import sys
144     opts, args = getopt(args, "", [])
145     opts = dict(opts)
146
147     if args == []:
148         print "usage: dulwich clone host:path [PATH]"
149         sys.exit(1)
150     client, host_path = get_transport_and_path(args.pop(0))
151
152     if len(args) > 0:
153         path = args.pop(0)
154     else:
155         path = host_path.split("/")[-1]
156
157     if not os.path.exists(path):
158         os.mkdir(path)
159     r = Repo.init(path)
160     remote_refs = client.fetch(host_path, r,
161         determine_wants=r.object_store.determine_wants_all,
162         progress=sys.stdout.write)
163     r["HEAD"] = remote_refs["HEAD"]
164
165
166 def cmd_commit(args):
167     from dulwich.repo import Repo
168     import os
169     opts, args = getopt(args, "", ["message"])
170     opts = dict(opts)
171     r = Repo(".")
172     committer = "%s <%s>" % (os.getenv("GIT_COMMITTER_NAME"), 
173                              os.getenv("GIT_COMMITTER_EMAIL"))
174     author = "%s <%s>" % (os.getenv("GIT_AUTHOR_NAME"), 
175                           os.getenv("GIT_AUTHOR_EMAIL"))
176     r.do_commit(committer=committer, author=author, message=opts["--message"])
177
178 commands = {
179     "commit": cmd_commit,
180     "fetch-pack": cmd_fetch_pack,
181     "dump-pack": cmd_dump_pack,
182     "dump-index": cmd_dump_index,
183     "init": cmd_init,
184     "log": cmd_log,
185     "clone": cmd_clone,
186     }
187
188 if len(sys.argv) < 2:
189     print "Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys()))
190     sys.exit(1)
191
192 cmd = sys.argv[1]
193 if not cmd in commands:
194     print "No such subcommand: %s" % cmd
195     sys.exit(1)
196 commands[cmd](sys.argv[2:])