aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2022-07-20 18:10:52 +0200
committerMatěj Cepl <mcepl@cepl.eu>2022-07-26 09:19:24 +0200
commitbd639314967d964f1116ddb757986d0b00e79328 (patch)
treeee5cdbf4525f3acb7a6e39feeba2d91c69a72bc1
parent650a225d66fba659164e6dcac3677caf1274f8b3 (diff)
downloadosc-fast-export-bd639314967d964f1116ddb757986d0b00e79328.tar.gz
Generate actual content of commits.
Should work even with binary files.
-rwxr-xr-xosc_fast_export.py56
1 files changed, 46 insertions, 10 deletions
diff --git a/osc_fast_export.py b/osc_fast_export.py
index 2bfa4d6..0042100 100755
--- a/osc_fast_export.py
+++ b/osc_fast_export.py
@@ -4,12 +4,18 @@
import collections
import configparser
from datetime import datetime
+import logging
+import os.path
import pathlib
import subprocess
+import sys
from typing import List
import xml.etree.ElementTree as ET
+logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO)
+log = logging.getLogger("osc_fast_export")
+
authorsfile = pathlib.Path(".git", "authorsfile.txt")
# For reading section-less config files
@@ -41,8 +47,9 @@ def osc_log() -> List[LogEntry]:
log_str = subprocess.run(
["osc", "log", "--xml"], check=True, text=True, stdout=subprocess.PIPE
).stdout
- except subprocess.CalledProcessError:
- raise
+ except subprocess.CalledProcessError as exc:
+ raise RuntimeError(f"Cannot collect log of the package!") from exc
+
tree = ET.fromstring(log_str)
log_list = [
LogEntry(
@@ -58,27 +65,56 @@ def osc_log() -> List[LogEntry]:
return log_list
-def export_data(dt: str) -> str:
- return f"data {len(dt)}\n{dt}"
+def checkout_revision(rev: int):
+ NULL = open(os.devnull, "wb")
+ try:
+ subprocess.check_call(
+ ["osc", "up", "-r", f"{rev}"], stdout=NULL, stderr=subprocess.PIPE
+ )
+ subprocess.check_call(["osc", "clean"], stdout=NULL, stderr=subprocess.PIPE)
+ except subprocess.CalledProcessError as exc:
+ raise RuntimeError(f"Cannot checkout revision {rev}!") from exc
def print_export(entry: LogEntry) -> int:
mark = entry.rev
author = authors.get(entry.author, "<none>")
- date = int(datetime.timestamp(entry.date))
+ checkout_revision(entry.rev)
print("commit refs/heads/master")
print(f"mark :{mark}")
if entry.md5:
print(f"original-oid {entry.md5}")
- print(f"committer {author} {date} +0000")
- print(export_data(entry.msg))
+ print(f"committer {author} {entry.date:%s} +0000")
+ print(f"data {len(entry.msg)}\n{entry.msg}")
if last_mark:
print(f"from :{last_mark}")
- # The following is dummy, needs to be replaced by actual content of each commit.
+
+ # Create actual content of the commit
+ # It is easier just to wipe out everything and include files again.
print("deleteall")
- print("M 644 inline tralala")
- print(export_data("tralalala"))
+ for dirpath, dirnames, filenames in os.walk("."):
+ # TODO are osc notes (aka osc comment) a thing?
+ dirpath = os.path.relpath(dirpath, ".")
+ if dirpath.startswith(".osc"):
+ continue
+ # It seems git-fast-export doesn't export directories at all
+ # and git-fast-import just creates them when needed.
+ # if dirpath != '.':
+ # # create directory
+ # print(f'M 040000 inline {dirpath}')
+ for fn in filenames:
+ fname = os.path.relpath(os.path.join(dirpath, fn), ".")
+ log.debug("dirpath = %s, fname = %s", dirpath, fname)
+ fstat = f"{os.stat(fname).st_mode:o}"
+ print(f"M {fstat} inline {fname}")
+ with open(fname, "rb") as inf:
+ dt = inf.read()
+ print(f"data {len(dt)}")
+ sys.stdout.flush()
+ with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as stdout:
+ stdout.write(dt)
+ stdout.flush()
print("")
return mark