Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a67bb3c

Browse files
committed
add git-synth for synthesizing git histories
1 parent f731577 commit a67bb3c

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

‎git-synth‎

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/python
2+
3+
import click
4+
import datetime
5+
import functools
6+
import os
7+
import subprocess
8+
import sys
9+
import yaml
10+
11+
from pathlib import Path
12+
13+
14+
class Git:
15+
def __init__(self, repo):
16+
self.repo = Path(repo)
17+
18+
def __call__(self, *args):
19+
return self._run_git('-C', self.repo, *args)
20+
21+
def init(self):
22+
return self._run_git('init', self.repo)
23+
24+
def _run_git(self, *args):
25+
out = subprocess.check_output(('git',) + args)
26+
return out
27+
28+
29+
def Date(val):
30+
if val in ['today', 'now']:
31+
date = datetime.datetime.now()
32+
else:
33+
date = datetime.datetime.fromisoformat(val)
34+
35+
return date
36+
37+
38+
@click.command()
39+
@click.option('-r', '--repo-path', default='testrepo', type=Path)
40+
@click.option('-n', '--name', default='demo')
41+
@click.option('-e', '--email', default='demo@example.com')
42+
@click.option('-d', '--date', type=Date)
43+
@click.argument('spec', type=click.File(mode='r'), default=sys.stdin)
44+
def main(repo_path, name, date, email, spec):
45+
if repo_path.is_dir():
46+
raise click.ClickException(f'directory {repo_path} already exists')
47+
48+
git = Git(repo_path)
49+
50+
os.environ.update({
51+
'GIT_AUTHOR_NAME': name,
52+
'GIT_COMMITTER_NAME': name,
53+
'GIT_AUTHOR_EMAIL': email,
54+
'GIT_COMMITTER_EMAIL': email,
55+
})
56+
57+
if date is not None:
58+
os.environ['GIT_AUTHOR_DATE'] = date.isoformat()
59+
os.environ['GIT_COMMITTER_DATE'] = date.isoformat()
60+
61+
with spec:
62+
hist = yaml.safe_load(spec)
63+
64+
stack = [iter(hist)]
65+
branches = []
66+
current_branch = None
67+
68+
git.init()
69+
70+
while stack:
71+
actlist = stack.pop()
72+
try:
73+
action = next(actlist)
74+
stack.append(actlist)
75+
except StopIteration:
76+
if branches:
77+
current_branch = branches.pop()
78+
git('switch', current_branch)
79+
continue
80+
81+
if 'branch' in action:
82+
if current_branch is not None:
83+
branches.append(current_branch)
84+
85+
branch = action['branch']
86+
git('switch', '-c', branch['name'])
87+
current_branch = branch['name']
88+
stack.append(iter(branch['actions']))
89+
continue
90+
elif 'commit' in action:
91+
commit = action['commit']
92+
print('commit', commit['message'])
93+
git('commit', '-m', commit['message'],
94+
'--allow-empty')
95+
elif 'file' in action:
96+
path = repo_path / action['file']['name']
97+
with path.open('w') as fd:
98+
fd.write(action['file']['content'])
99+
git('add', action['file']['name'])
100+
elif 'set' in action:
101+
if 'date' in action['set']:
102+
os.environ['GIT_AUTHOR_DATE'] = Date(action['set']['date']).isoformat()
103+
os.environ['GIT_COMMITTER_DATE'] = Date(action['set']['date']).isoformat()
104+
if 'name' in action['set']:
105+
os.environ['GIT_AUTHOR_NAME'] = action['set']['name']
106+
os.environ['GIT_COMMITTER_NAME'] = action['set']['name']
107+
if 'email' in action['set']:
108+
os.environ['GIT_AUTHOR_EMAIL'] = action['set']['email']
109+
os.environ['GIT_COMMITTER_EMAIL'] = action['set']['email']
110+
elif 'setenv' in action:
111+
for k, v in action['setenv'].items():
112+
os.environ[k] = v
113+
114+
115+
if __name__ == '__main__':
116+
main()

‎repo-1.json‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- set:
2+
date: "2021年01月01日"
3+
name: Fake Person
4+
email: fake@example.com
5+
- branch:
6+
name: master
7+
actions:
8+
- commit:
9+
message: A
10+
- commit:
11+
message: B
12+
- commit:
13+
message: C
14+
- branch:
15+
name: topic1
16+
actions:
17+
- commit:
18+
message: D
19+
- commit:
20+
message: E
21+
- branch:
22+
name: topic2
23+
actions:
24+
- commit:
25+
message: F
26+
- commit:
27+
message: G

‎repo-2.json‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- set:
2+
date: "2021年01月01日"
3+
name: Fake Person
4+
email: fake@example.com
5+
- branch:
6+
name: master
7+
actions:
8+
- commit:
9+
message: A
10+
- commit:
11+
message: B
12+
- commit:
13+
message: C
14+
- branch:
15+
name: topic1
16+
actions:
17+
- commit:
18+
message: D
19+
- commit:
20+
message: E
21+
- branch:
22+
name: topic2
23+
actions:
24+
- commit:
25+
message: F
26+
- commit:
27+
message: G

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /