Merge fixes from abderrahim.
[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         if "--all" in opts:
39                 determine_wants = r.object_store.determine_wants_all
40         else:
41                 determine_wants = lambda x: [y for y in args if not y in r.object_store]
42         r = Repo(".")
43         graphwalker = r.get_graph_walker()
44         f, commit = r.object_store.add_pack()
45         try:
46             client.fetch_pack(path, determine_wants, graphwalker, f.write, sys.stdout.write)
47         finally:
48                 commit()
49
50
51 def cmd_log(args):
52         from dulwich.repo import Repo
53         opts, args = getopt(args, "", [])
54         r = Repo(".")
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         import sys
124         opts, args = getopt(args, "", ["--bare"])
125         opts = dict(opts)
126
127         if args == []:
128                 path = os.getcwd()
129         else:
130                 path = args[0]
131
132         if not os.path.exists(path):
133                 os.mkdir(path)
134
135         if "--bare" in opts:
136                 Repo.init_bare(path)
137         else:
138                 Repo.init(path)
139
140
141 def cmd_clone(args):
142         from dulwich.repo import Repo
143         import os
144         import sys
145         opts, args = getopt(args, "", [])
146         opts = dict(opts)
147
148         if args == []:
149                 print "usage: dulwich clone host:path [PATH]"
150                 sys.exit(1)
151         client, host_path = get_transport_and_path(args.pop(0))
152
153         if len(args) > 0:
154                 path = args.pop(0)
155         else:
156                 path = host_path.split("/")[-1]
157
158         if not os.path.exists(path):
159                 os.mkdir(path)
160         Repo.init(path)
161         r = Repo(path)
162         graphwalker = r.get_graph_walker()
163         f, commit = r.object_store.add_pack()
164         client.fetch_pack(host_path, r.object_store.determine_wants_all, 
165                                   graphwalker, f.write, sys.stdout.write)
166         commit()
167
168
169 commands = {
170         "fetch-pack": cmd_fetch_pack,
171         "dump-pack": cmd_dump_pack,
172         "dump-index": cmd_dump_index,
173         "init": cmd_init,
174         "log": cmd_log,
175         "clone": cmd_clone,
176         }
177
178 if len(sys.argv) < 2:
179         print "Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys()))
180         sys.exit(1)
181
182 cmd = sys.argv[1]
183 if not cmd in commands:
184         print "No such subcommand: %s" % cmd
185         sys.exit(1)
186 commands[cmd](sys.argv[2:])