aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/version.py
blob: bf8d5091c9cce926263a20babd478fc8f6c54b54 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import datetime
import subprocess

__all__ = ("get_version",)


def get_version() -> str:
    """
    Return a version based on the HEAD commit's date.

    The format is 'year.month.day.commits' and is compliant with PEP 440. 'commits' is the amount of
    commits made on the same date as HEAD, excluding HEAD. This ensures versions are unique if
    multiple release occur on the same date.
    """
    args = ["git", "show", "-s", "--format=%ct", "HEAD"]
    stdout = subprocess.check_output(args, text=True)
    timestamp = float(stdout.strip())
    date = datetime.datetime.fromtimestamp(timestamp, datetime.timezone.utc)

    commits = count_commits_on_date(date) - 1  # Exclude HEAD.

    # Don't use strftime because it includes leading zeros, which are against PEP 440.
    return f"{date.year}.{date.month}.{date.day}.{commits}"


def count_commits_on_date(dt: datetime.datetime) -> int:
    """Return the amount of commits made on the given UTC aware datetime."""
    dt = dt.combine(dt - datetime.timedelta(days=1), dt.max.time(), dt.tzinfo)

    # git log uses the committer date for this, not the author date.
    args = ["git", "log", "--oneline", "--after", str(dt.timestamp())]
    stdout = subprocess.check_output(args, text=True)

    return stdout.strip().count("\n")


if __name__ == "__main__":
    print(get_version())