Browse Source

Add porcelain.remote_add.

Jelmer Vernooij 8 years ago
parent
commit
0c8bd2b3e7
5 changed files with 69 additions and 0 deletions
  1. 4 0
      NEWS
  2. 15 0
      bin/dulwich
  3. 8 0
      dulwich/config.py
  4. 25 0
      dulwich/porcelain.py
  5. 17 0
      dulwich/tests/test_porcelain.py

+ 4 - 0
NEWS

@@ -26,6 +26,10 @@
   * Remove racy check that relies on clock time changing between writes.
     (Jelmer Vernooij)
 
+ IMPROVEMENTS
+
+  * Add porcelain.remote_add. (Jelmer Vernooij)
+
 0.16.2	2016-01-14
 
  IMPROVEMENTS

+ 15 - 0
bin/dulwich

@@ -468,6 +468,20 @@ class cmd_pack_objects(Command):
             f.close()
 
 
+def cmd_remote_add(args):
+    parser = optparse.OptionParser()
+    options, args = parser.parse_args(args)
+    porcelain.remote_add('.', args[0], args[1])
+
+
+def cmd_remote(args):
+    subcommands = {
+        "add": cmd_remote_add,
+    }
+    cmd = args[0]
+    return subcommands[cmd](args[1:])
+
+
 class cmd_help(Command):
 
     def run(self, args):
@@ -510,6 +524,7 @@ commands = {
     "ls-tree": cmd_ls_tree,
     "pack-objects": cmd_pack_objects,
     "receive-pack": cmd_receive_pack,
+    "remote": cmd_remote,
     "repack": cmd_repack,
     "reset": cmd_reset,
     "rev-list": cmd_rev_list,

+ 8 - 0
dulwich/config.py

@@ -95,6 +95,14 @@ class Config(object):
         """
         raise NotImplementedError(self.itersections)
 
+    def has_section(self, name):
+        """Check if a specified section exists.
+
+        :param name: Name of section to check for
+        :return: boolean indicating whether the section exists
+        """
+        return (name in self.itersections())
+
 
 class ConfigDict(Config, MutableMapping):
     """Git configuration stored in a dictionary."""

+ 25 - 0
dulwich/porcelain.py

@@ -36,6 +36,7 @@ Currently implemented:
  * pull
  * push
  * rm
+ * remote{_add}
  * receive-pack
  * reset
  * rev-list
@@ -121,6 +122,10 @@ default_bytes_err_stream = getattr(sys.stderr, 'buffer', sys.stderr)
 DEFAULT_ENCODING = 'utf-8'
 
 
+class RemoteExists(Exception):
+    """Raised when the remote already exists."""
+
+
 def open_repo(path_or_repo):
     """Open an argument that can be a repository or a path for a repository."""
     if isinstance(path_or_repo, BaseRepo):
@@ -977,3 +982,23 @@ def ls_tree(repo, tree_ish=None, outstream=sys.stdout, recursive=False,
         c = r[tree_ish]
         treeid = c.tree
         list_tree(r.object_store, treeid, "")
+
+
+def remote_add(repo, name, url):
+    """Add a remote.
+
+    :param repo: Path to the repository
+    :param name: Remote name
+    :param url: Remote URL
+    """
+    if not isinstance(name, bytes):
+        name = name.encode(DEFAULT_ENCODING)
+    if not isinstance(url, bytes):
+        url = url.encode(DEFAULT_ENCODING)
+    with open_repo_closing(repo) as r:
+        c = r.get_config()
+        section = (b'remote', name)
+        if c.has_section(section):
+            raise RemoteExists(section)
+        c.set(section, b"url", url)
+        c.write_to_path()

+ 17 - 0
dulwich/tests/test_porcelain.py

@@ -902,3 +902,20 @@ class LsRemoteTests(PorcelainTestCase):
             b'refs/heads/master': cid,
             b'HEAD': cid},
             porcelain.ls_remote(self.repo.path))
+
+
+class RemoteAddTests(PorcelainTestCase):
+
+    def test_new(self):
+        porcelain.remote_add(
+            self.repo, 'jelmer', 'git://jelmer.uk/code/dulwich')
+        c = self.repo.get_config()
+        self.assertEqual(
+            c.get((b'remote', b'jelmer'), b'url'),
+            b'git://jelmer.uk/code/dulwich')
+
+    def test_exists(self):
+        porcelain.remote_add(
+            self.repo, 'jelmer', 'git://jelmer.uk/code/dulwich')
+        self.assertRaises(porcelain.RemoteExists, porcelain.remote_add,
+            self.repo, 'jelmer', 'git://jelmer.uk/code/dulwich')