Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions src/cfengine_cli/masterfiles/generate_git_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import re
import os
import subprocess
from collections import OrderedDict
from cfbs.utils import (
write_json,
)

CACHE_DIR = "cache/git/github.com"
TARGET_DIR = "git/github.com"

TAG_REGEX = re.compile(r"v?\d+\.\d+\.\d+(-\d+)?")

REPOS = [
"cfengine/core",
"cfengine/enterprise",
"cfengine/nova",
"cfengine/mission-portal",
"cfengine/buildscripts",
"cfengine/masterfiles",
]


def clone_or_update_repo(repo):
# Clone repo if not present, else fetch latest version
repo_path = os.path.join(CACHE_DIR, repo)

if os.path.isdir(repo_path):
print(f"Updating {repo}...")
subprocess.run(["git", "fetch", "--tags"], cwd=repo_path, check=True)

else:
print(f"Cloning {repo}...")
os.makedirs(os.path.dirname(repo_path), exist_ok=True)
subprocess.run(
["git", "clone", f"git@github.com:{repo}.git", repo_path],
check=True,
)
return repo_path


def get_commit_shas_from_tags(repo_path):
# Returns a mapping of git tag to commit SHA for all version tags in the repo
output = (
subprocess.check_output(["git", "show-ref", "--tags"], cwd=repo_path)
.decode()
.strip()
)
tag_map = {}

for line in output.splitlines():
ref = line.split()[1]
tag = ref.split("refs/tags/")[1]
if re.fullmatch(TAG_REGEX, tag):
sha = (
subprocess.check_output(
["git", "log", "-n", "1", "--format=%H", tag], cwd=repo_path
)
.decode()
.strip()
)
tag_map[tag] = sha
Comment on lines +51 to +62
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of using git show-ref --tags was to eliminate these unnecessary subprocesses, I made a mistake when showing you the command, this is the correct version of it;

git show-ref --tags -d

With that command, you get all the information you need in just 1 process instead of having to call git log again and again;

bac5b9cd69d91179eca01f2af9ebae16a4eb29d7 refs/tags/3.27.0
4c3834d679d5f03adc8a853f8481680ade44dd5a refs/tags/3.27.0^{}

The lines ending with ^{} have the correct commit SHA for that version.


return tag_map


def build_tag_map(repo):
repo_path = clone_or_update_repo(repo)
tag_map = get_commit_shas_from_tags(repo_path)

return sort_git_tags(tag_map)


def write_tag_map(repo, tag_map):
repo_dir = os.path.join(TARGET_DIR, repo)
os.makedirs(repo_dir, exist_ok=True)
write_json(f"{repo_dir}/tags.json", tag_map)


def sort_git_tags(tag_map):
# Sorts git tags by version descending
return OrderedDict(
sorted(
tag_map.items(),
reverse=True,
key=lambda item: tuple(
int(x) for x in item[0].lstrip("v").replace("-", ".").split(".")
),
)
)


def generate_git_tags_map():
os.makedirs(TARGET_DIR, exist_ok=True)
os.makedirs(CACHE_DIR, exist_ok=True)
for repo in REPOS:
print(f"\nProcessing {repo}...")
tag_map = build_tag_map(repo)
write_tag_map(repo, tag_map)
5 changes: 5 additions & 0 deletions src/cfengine_cli/masterfiles/generate_release_information.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from cfengine_cli.masterfiles.check_download_matches_git import (
check_download_matches_git,
)
from cfengine_cli.masterfiles.generate_git_tags import (
generate_git_tags_map,
)
from cfbs.utils import (
get_json,
immediate_subdirectories,
Expand Down Expand Up @@ -46,6 +49,8 @@ def generate_release_information_impl(

generate_release_history()

generate_git_tags_map()

if check:
print(
"Downloading releases of masterfiles from git (github.com) and generating "
Expand Down
Loading