Add 'add' command to porcelain.
[jelmer/dulwich.git] / bin / dulwich
index 7d587af0b8bf2999a1ab2f2e731e1c244b4d22ec..3a7a610a7a5fcd0ac6eae03c40288a4d4a84f83a 100755 (executable)
-#!/usr/bin/python
-# dul-daemon - Simple git smart server client
-# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
-# 
+#!/usr/bin/python -u
+#
+# dulwich - Simple command-line interface to Dulwich
+# Copyright (C) 2008-2011 Jelmer Vernooij <jelmer@samba.org>
+# vim: expandtab
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; version 2
 # or (at your option) a later version of the License.
-# 
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
+"""Simple command-line interface to Dulwich>
+
+This is a very simple command-line wrapper for Dulwich. It is by 
+no means intended to be a full-blown Git command-line interface but just 
+a way to test Dulwich.
+"""
+
+import os
 import sys
 from getopt import getopt
 
-def get_transport_and_path(uri):
-    from dulwich.client import TCPGitClient, SSHGitClient, SubprocessGitClient
-    for handler, transport in (("git://", TCPGitClient), ("git+ssh://", SSHGitClient)):
-        if uri.startswith(handler):
-            host, path = uri[len(handler):].split("/", 1)
-            return transport(host), "/"+path
-    # if its not git or git+ssh, try a local url..
-    return SubprocessGitClient(), uri
+from dulwich import porcelain
+from dulwich.client import get_transport_and_path
+from dulwich.errors import ApplyDeltaError
+from dulwich.index import Index
+from dulwich.pack import Pack, sha_to_hex
+from dulwich.patch import write_tree_diff
+from dulwich.repo import Repo
+
+
+def cmd_archive(args):
+    opts, args = getopt(args, "", [])
+    client, path = get_transport_and_path(args.pop(0))
+    location = args.pop(0)
+    committish = args.pop(0)
+    porcelain.archive(location, committish, outstream=sys.stdout,
+        errstream=sys.stderr)
+
+
+def cmd_add(args):
+    opts, args = getopt(args, "", [])
+
+    porcelain.add(".", paths=args)
 
 
 def cmd_fetch_pack(args):
-       from dulwich.client import SimpleFetchGraphWalker
-       from dulwich.repo import Repo
-       opts, args = getopt(args, "", ["all"])
-       opts = dict(opts)
-        client, path = get_transport_and_path(args.pop(0))
-       if "--all" in opts:
-               determine_wants = r.object_store.determine_wants_all
-       else:
-               determine_wants = lambda x: [y for y in args if not y in r.object_store]
-       r = Repo(".")
-       graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
-       f, commit = r.object_store.add_pack()
-       try:
-               client.fetch_pack(path, determine_wants, graphwalker, f.write, sys.stdout.write)
-               f.close()
-               commit()
-       except:
-               f.close()
-               raise
+    opts, args = getopt(args, "", ["all"])
+    opts = dict(opts)
+    client, path = get_transport_and_path(args.pop(0))
+    r = Repo(".")
+    if "--all" in opts:
+        determine_wants = r.object_store.determine_wants_all
+    else:
+        determine_wants = lambda x: [y for y in args if not y in r.object_store]
+    client.fetch(path, r, determine_wants)
+
+
+def cmd_fetch(args):
+    opts, args = getopt(args, "", [])
+    opts = dict(opts)
+    client, path = get_transport_and_path(args.pop(0))
+    r = Repo(".")
+    if "--all" in opts:
+        determine_wants = r.object_store.determine_wants_all
+    refs = client.fetch(path, r, progress=sys.stdout.write)
+    print "Remote refs:"
+    for item in refs.iteritems():
+        print "%s -> %s" % item
 
 
 def cmd_log(args):
-       from dulwich.repo import Repo
-       opts, args = getopt(args, "", [])
-       r = Repo(".")
-       todo = [r.head()]
-       done = set()
-       while todo:
-               sha = todo.pop()
-               assert isinstance(sha, str)
-               if sha in done:
-                       continue
-               done.add(sha)
-               commit = r.commit(sha)
-               print "-" * 50
-               print "commit: %s" % sha
-               if len(commit.parents) > 1:
-                       print "merge: %s" % "...".join(commit.parents[1:])
-               print "author: %s" % commit.author
-               print "committer: %s" % commit.committer
-               print ""
-               print commit.message
-               print ""
-               todo.extend([p for p in commit.parents if p not in done])
+    opts, args = getopt(args, "", [])
+    if len(args) > 0:
+        path = args.pop(0)
+    else:
+        path = "."
+    r = Repo(path)
+    todo = [r.head()]
+    done = set()
+    while todo:
+        sha = todo.pop()
+        assert isinstance(sha, str)
+        if sha in done:
+            continue
+        done.add(sha)
+        commit = r[sha]
+        print "-" * 50
+        print "commit: %s" % sha
+        if len(commit.parents) > 1:
+            print "merge: %s" % "...".join(commit.parents[1:])
+        print "author: %s" % commit.author
+        print "committer: %s" % commit.committer
+        print ""
+        print commit.message
+        print ""
+        todo.extend([p for p in commit.parents if p not in done])
+
+
+def cmd_diff(args):
+    opts, args = getopt(args, "", [])
+
+    if args == []:
+        print "Usage: dulwich diff COMMITID"
+        sys.exit(1)
+
+    r = Repo(".")
+    commit_id = args[0]
+    commit = r[commit_id]
+    parent_commit = r[commit.parents[0]]
+    write_tree_diff(sys.stdout, r.object_store, parent_commit.tree, commit.tree)
 
 
 def cmd_dump_pack(args):
-       from dulwich.errors import ApplyDeltaError
-       from dulwich.pack import Pack, sha_to_hex
-       import os
-       import sys
-
-       opts, args = getopt(args, "", [])
-
-       if args == []:
-               print "Usage: dulwich dump-pack FILENAME"
-               sys.exit(1)
-
-       basename, _ = os.path.splitext(args[0])
-       x = Pack(basename)
-       print "Object names checksum: %s" % x.name()
-       print "Checksum: %s" % sha_to_hex(x.get_stored_checksum())
-       if not x.check():
-               print "CHECKSUM DOES NOT MATCH"
-       print "Length: %d" % len(x)
-       for name in x:
-               try:
-                       print "\t%s" % x[name]
-               except KeyError, k:
-                       print "\t%s: Unable to resolve base %s" % (name, k)
-               except ApplyDeltaError, e:
-                       print "\t%s: Unable to apply delta: %r" % (name, e)
+    opts, args = getopt(args, "", [])
+
+    if args == []:
+        print "Usage: dulwich dump-pack FILENAME"
+        sys.exit(1)
+
+    basename, _ = os.path.splitext(args[0])
+    x = Pack(basename)
+    print "Object names checksum: %s" % x.name()
+    print "Checksum: %s" % sha_to_hex(x.get_stored_checksum())
+    if not x.check():
+        print "CHECKSUM DOES NOT MATCH"
+    print "Length: %d" % len(x)
+    for name in x:
+        try:
+            print "\t%s" % x[name]
+        except KeyError, k:
+            print "\t%s: Unable to resolve base %s" % (name, k)
+        except ApplyDeltaError, e:
+            print "\t%s: Unable to apply delta: %r" % (name, e)
 
 
 def cmd_dump_index(args):
-       from dulwich.index import Index
-
-       opts, args = getopt(args, "", [])
+    opts, args = getopt(args, "", [])
 
-       if args == []:
-               print "Usage: dulwich dump-pack FILENAME"
-               sys.exit(1)
+    if args == []:
+        print "Usage: dulwich dump-index FILENAME"
+        sys.exit(1)
 
-       filename = args[0]
-       idx = Index(filename)
+    filename = args[0]
+    idx = Index(filename)
 
-       for o in idx:
-               print o, idx[o]
+    for o in idx:
+        print o, idx[o]
 
 
 def cmd_init(args):
-       from dulwich.repo import Repo
-       import os
-       import sys
-       opts, args = getopt(args, "", ["--bare"])
-       opts = dict(opts)
+    opts, args = getopt(args, "", ["bare"])
+    opts = dict(opts)
 
-       if args == []:
-               path = os.getcwd()
-       else:
-               path = args[0]
+    if args == []:
+        path = os.getcwd()
+    else:
+        path = args[0]
 
-       if not os.path.exists(path):
-               os.mkdir(path)
-
-       if "--bare" in opts:
-               Repo.init_bare(path)
-       else:
-               Repo.init(path)
+    porcelain.init(path, bare=("--bare" in opts))
 
 
 def cmd_clone(args):
-       from dulwich.client import SimpleFetchGraphWalker
-       from dulwich.repo import Repo
-       import os
-       import sys
-       opts, args = getopt(args, "", [])
-       opts = dict(opts)
-
-       if args == []:
-               print "usage: dulwich clone host:path [PATH]"
-               sys.exit(1)
-        client, host_path = get_transport_and_path(args.pop(0))
-
-       if len(args) > 0:
-               path = args.pop(0)
-       else:
-               path = host_path.split("/")[-1]
-
-       if not os.path.exists(path):
-               os.mkdir(path)
-       Repo.init(path)
-       r = Repo(path)
-       graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
-       f, commit = r.object_store.add_pack()
-       client.fetch_pack(host_path, r.object_store.determine_wants_all, 
-                                 graphwalker, f.write, sys.stdout.write)
-       commit()
+    opts, args = getopt(args, "", ["bare"])
+    opts = dict(opts)
+
+    if args == []:
+        print "usage: dulwich clone host:path [PATH]"
+        sys.exit(1)
+
+    source = args.pop(0)
+    if len(args) > 0:
+        target = args.pop(0)
+    else:
+        target = None
+
+    porcelain.clone(source, target, bare=("--bare" in opts))
+
+
+def cmd_commit(args):
+    opts, args = getopt(args, "", ["message"])
+    opts = dict(opts)
+    porcelain.commit(".", message=opts["--message"])
+
+
+def cmd_update_server_info(args):
+    porcelain.update_server_info(".")
 
 
 commands = {
-       "fetch-pack": cmd_fetch_pack,
-       "dump-pack": cmd_dump_pack,
-       "dump-index": cmd_dump_index,
-       "init": cmd_init,
-       "log": cmd_log,
-       "clone": cmd_clone,
-       }
+    "commit": cmd_commit,
+    "fetch-pack": cmd_fetch_pack,
+    "fetch": cmd_fetch,
+    "dump-pack": cmd_dump_pack,
+    "dump-index": cmd_dump_index,
+    "init": cmd_init,
+    "log": cmd_log,
+    "clone": cmd_clone,
+    "archive": cmd_archive,
+    "update-server-info": cmd_update_server_info,
+    "diff": cmd_diff,
+    }
 
 if len(sys.argv) < 2:
-       print "Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys()))
-       sys.exit(1)
+    print "Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys()))
+    sys.exit(1)
 
 cmd = sys.argv[1]
 if not cmd in commands:
-       print "No such subcommand: %s" % cmd
-       sys.exit(1)
+    print "No such subcommand: %s" % cmd
+    sys.exit(1)
 commands[cmd](sys.argv[2:])