Преглед на файлове

Simple describe implementation

Sylvia van Os преди 6 години
родител
ревизия
6572813375
променени са 2 файла, в които са добавени 80 реда и са изтрити 0 реда
  1. 9 0
      bin/dulwich
  2. 71 0
      dulwich/porcelain.py

+ 9 - 0
bin/dulwich

@@ -614,6 +614,14 @@ class cmd_ls_files(Command):
             print(name)
 
 
+class cmd_describe(Command):
+
+    def run(self, args):
+        parser = optparse.OptionParser()
+        options, args = parser.parse_args(args)
+        print(porcelain.describe('.'))
+
+
 class cmd_help(Command):
 
     def run(self, args):
@@ -644,6 +652,7 @@ commands = {
     "clone": cmd_clone,
     "commit": cmd_commit,
     "commit-tree": cmd_commit_tree,
+    "describe": cmd_describe,
     "daemon": cmd_daemon,
     "diff": cmd_diff,
     "diff-tree": cmd_diff_tree,

+ 71 - 0
dulwich/porcelain.py

@@ -30,6 +30,7 @@ Currently implemented:
  * commit
  * commit-tree
  * daemon
+ * describe
  * diff-tree
  * fetch
  * init
@@ -61,6 +62,7 @@ from contextlib import (
     contextmanager,
 )
 from io import BytesIO
+import datetime
 import os
 import posixpath
 import stat
@@ -1286,3 +1288,72 @@ def ls_files(repo):
     """List all files in an index."""
     with open_repo_closing(repo) as r:
         return sorted(r.open_index())
+
+
+def describe(repo):
+    """Describe the repository version.
+
+    :param projdir: git repository root
+    :returns: a string description of the current git revision
+
+    Examples: "gabcdefh", "v0.1" or "v0.1-5-gabcdefh".
+    """
+    # Get the repository
+    with open_repo_closing(repo) as r:
+        # Get a list of all tags
+        refs = r.get_refs()
+        tags = {}
+        for key, value in refs.items():
+            key = key.decode()
+            obj = r.get_object(value)
+            if u'tags' not in key:
+                continue
+
+            _, tag = key.rsplit(u'/', 1)
+
+            try:
+                commit = obj.object
+            except AttributeError:
+                continue
+            else:
+                commit = r.get_object(commit[1])
+            tags[tag] = [
+                datetime.datetime(*time.gmtime(commit.commit_time)[:6]),
+                commit.id.decode('utf-8'),
+            ]
+
+        sorted_tags = sorted(tags.items(),
+                             key=lambda tag: tag[1][0],
+                             reverse=True)
+
+        # If there are no tags, return the current commit
+        if len(sorted_tags) == 0:
+            return 'g{}'.format(r[r.head()].id.decode('utf-8')[:7])
+
+        # We're now 0 commits from the top
+        commit_count = 0
+
+        # Get the latest commit
+        latest_commit = r[r.head()]
+
+        # Walk through all commits
+        walker = r.get_walker()
+        for entry in walker:
+            # Check if tag
+            commit_id = entry.commit.id.decode('utf-8')
+            for tag in sorted_tags:
+                tag_name = tag[0]
+                tag_commit = tag[1][1]
+                if commit_id == tag_commit:
+                    if commit_count == 0:
+                        return tag_name
+                    else:
+                        return '{}-{}-g{}'.format(
+                                tag_name,
+                                commit_count,
+                                latest_commit.id.decode('utf-8')[:7])
+
+            commit_count += 1
+
+        # Return plain commit if no parent tag can be found
+        return 'g{}'.format(latest_commit.id.decode('utf-8')[:7])