release 0.6.1.
[jelmer/dulwich-libgit2.git] / bin / dulwich
1 #!/usr/bin/python
2 # dulwich - Simple command-line interface to Dulwich
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 """Simple command-line interface to Dulwich>
21
22 This is a very simple command-line wrapper for Dulwich. It is by 
23 no means intended to be a full-blown Git command-line interface but just 
24 a way to test Dulwich.
25 """
26
27 import os
28 import sys
29 from getopt import getopt
30
31 from dulwich.client import get_transport_and_path
32 from dulwich.errors import ApplyDeltaError
33 from dulwich.index import Index
34 from dulwich.pack import Pack, sha_to_hex
35 from dulwich.repo import Repo
36
37
38 def cmd_fetch_pack(args):
39     opts, args = getopt(args, "", ["all"])
40     opts = dict(opts)
41     client, path = get_transport_and_path(args.pop(0))
42     r = Repo(".")
43     if "--all" in opts:
44         determine_wants = r.object_store.determine_wants_all
45     else:
46         determine_wants = lambda x: [y for y in args if not y in r.object_store]
47     graphwalker = r.get_graph_walker()
48     client.fetch(path, r.object_store, determine_wants)
49
50
51 def cmd_log(args):
52     opts, args = getopt(args, "", [])
53     if len(args) > 0:
54         path = args.pop(0)
55     else:
56         path = "."
57     r = Repo(path)
58     todo = [r.head()]
59     done = set()
60     while todo:
61         sha = todo.pop()
62         assert isinstance(sha, str)
63         if sha in done:
64             continue
65         done.add(sha)
66         commit = r[sha]
67         print "-" * 50
68         print "commit: %s" % sha
69         if len(commit.parents) > 1:
70             print "merge: %s" % "...".join(commit.parents[1:])
71         print "author: %s" % commit.author
72         print "committer: %s" % commit.committer
73         print ""
74         print commit.message
75         print ""
76         todo.extend([p for p in commit.parents if p not in done])
77
78
79 def cmd_dump_pack(args):
80     opts, args = getopt(args, "", [])
81
82     if args == []:
83         print "Usage: dulwich dump-pack FILENAME"
84         sys.exit(1)
85
86     basename, _ = os.path.splitext(args[0])
87     x = Pack(basename)
88     print "Object names checksum: %s" % x.name()
89     print "Checksum: %s" % sha_to_hex(x.get_stored_checksum())
90     if not x.check():
91         print "CHECKSUM DOES NOT MATCH"
92     print "Length: %d" % len(x)
93     for name in x:
94         try:
95             print "\t%s" % x[name]
96         except KeyError, k:
97             print "\t%s: Unable to resolve base %s" % (name, k)
98         except ApplyDeltaError, e:
99             print "\t%s: Unable to apply delta: %r" % (name, e)
100
101
102 def cmd_dump_index(args):
103     opts, args = getopt(args, "", [])
104
105     if args == []:
106         print "Usage: dulwich dump-index FILENAME"
107         sys.exit(1)
108
109     filename = args[0]
110     idx = Index(filename)
111
112     for o in idx:
113         print o, idx[o]
114
115
116 def cmd_init(args):
117     opts, args = getopt(args, "", ["--bare"])
118     opts = dict(opts)
119
120     if args == []:
121         path = os.getcwd()
122     else:
123         path = args[0]
124
125     if not os.path.exists(path):
126         os.mkdir(path)
127
128     if "--bare" in opts:
129         Repo.init_bare(path)
130     else:
131         Repo.init(path)
132
133
134 def cmd_clone(args):
135     opts, args = getopt(args, "", [])
136     opts = dict(opts)
137
138     if args == []:
139         print "usage: dulwich clone host:path [PATH]"
140         sys.exit(1)
141     client, host_path = get_transport_and_path(args.pop(0))
142
143     if len(args) > 0:
144         path = args.pop(0)
145     else:
146         path = host_path.split("/")[-1]
147
148     if not os.path.exists(path):
149         os.mkdir(path)
150     r = Repo.init(path)
151     remote_refs = client.fetch(host_path, r,
152         determine_wants=r.object_store.determine_wants_all,
153         progress=sys.stdout.write)
154     r["HEAD"] = remote_refs["HEAD"]
155
156
157 def cmd_commit(args):
158     opts, args = getopt(args, "", ["message"])
159     opts = dict(opts)
160     r = Repo(".")
161     committer = "%s <%s>" % (os.getenv("GIT_COMMITTER_NAME"), 
162                              os.getenv("GIT_COMMITTER_EMAIL"))
163     author = "%s <%s>" % (os.getenv("GIT_AUTHOR_NAME"), 
164                           os.getenv("GIT_AUTHOR_EMAIL"))
165     r.do_commit(committer=committer, author=author, message=opts["--message"])
166
167
168 commands = {
169     "commit": cmd_commit,
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:])