|
@@ -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])
|