-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathginit
executable file
·166 lines (147 loc) · 5.8 KB
/
ginit
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python3
from __future__ import annotations
from typing import Any
import argparse
import sys
import os
import shutil
import subprocess
import textwrap
import time
from lib.config import Config
from lib.utilities import get_root_dir, safe_makedirs
def main() -> None:
""" The main entry point for ginit. """
start_time = time.time()
try:
is_help_triggered = any(arg in sys.argv for arg in ["-h", "--help"])
args = parse_system_args()
destination_dir = args.get("path", ".")
config = GinitConfig()
source_dir = config.data.get("source_dir")
if args.get("config"):
config.initialize_config()
else:
if not args.get("init_only"):
copy_metadata(source_dir, destination_dir)
if not args.get("file_only"):
execute_git(destination_dir)
if not is_help_triggered:
print(f"Finished in {round(time.time() - start_time, 2)} seconds.")
sys.exit(0)
except (Exception, KeyboardInterrupt) as error:
if hasattr(error, 'code') and isinstance(error.code, int):
exit_code = error.code
else:
exit_code = 1
print(error)
if not is_help_triggered:
print(
f"Exited after {round(time.time() - start_time, 2)} seconds.")
sys.exit(exit_code)
class GinitConfig(Config):
""" The config file for ginit. """
def __init__(self) -> None:
super().__init__(file_name="ginit", version="2.0.0")
self.input_functions = [self._input_source_dir]
self.read_config()
def _input_source_dir(self) -> str:
while True:
print("Enter the metadata source directory path")
print("(default: '<script-location>/ginit-files/')")
src = input(": ") or os.path.join(get_root_dir(), "ginit-files")
# check if user specify a relative path or absolute path
if os.path.isabs(src):
source_dir = os.path.realpath(src)
else:
source_dir = os.path.realpath(
os.path.join(os.getcwd(), *src.split("/")))
print(source_dir)
if not os.path.isdir(source_dir):
print(f"{source_dir} is not a directory.")
elif (input("Is this the right path (y/n)? ") or "y") == "y":
break
return {"source_dir": source_dir}
def parse_system_args() -> dict[str, Any]:
""" Parse command line arguments. """
parser = argparse.ArgumentParser(
description="Initialize a new project with Git and metadata files.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent("""
examples:
$ python ginit
Copy all files in source directory to current directory
and initialize the Git repository.
$ python ginit /path/to/destination
Copy all files in source directory to `/path/to/destination`
and initialize the Git repository.
$ python ginit --init-only
Only initialize the Git repository.
$ python ginit -h
Print this help message and sys.exit.
A Python utility to initialize a Git repository and copy all files
from the source directory specified in the config file (ginit.json)
to the destination directory.
""")
)
parser.add_argument(
"path",
nargs="?",
default=".",
help="the destination directory path. (default: .)"
)
partial_execution_group = parser.add_mutually_exclusive_group()
partial_execution_group.add_argument(
"-c", "--config",
help="create the config file",
action="store_true"
)
partial_execution_group.add_argument(
"-io", "--init-only",
action="store_true",
help="only initialize the Git repository.",
dest="init_only"
)
partial_execution_group.add_argument(
"-fo", "--file-only",
action="store_true",
help="only copy metadata files to destination directory.",
dest="file_only"
)
return vars(parser.parse_args())
def copy_metadata(source_dir: str, destination_dir: str) -> None:
""" Copy all files in source directory to destination directory. """
if not os.path.exists(source_dir):
raise Exception(f"{source_dir} not found.")
real_destination_dir = safe_makedirs(destination_dir)
print(f"Copying metadata files to {real_destination_dir}.")
for entry in os.scandir(source_dir):
destination_path = os.path.realpath(
os.path.join(real_destination_dir, entry.name))
if os.path.exists(destination_path):
print(f"- {destination_path} is already exists. Skipped.")
continue
if entry.is_file():
shutil.copy(entry.path, destination_path)
elif entry.is_dir():
shutil.copytree(entry.path, destination_path)
else:
raise Exception(
f"What happened? {entry.path} is not a file or directory.")
def execute_git(destination_dir: str) -> None:
"""
Initialize Git repository in the given destination_dir and ask user
to commit now or not.
"""
return_code = 0
real_destination_dir = safe_makedirs(destination_dir)
subprocess.call(["git", "init"], cwd=real_destination_dir)
subprocess.call(["git", "add", "."], cwd=real_destination_dir)
print("Added all files to the staging area.")
if input("Commit? (y/n): ") == "y":
return_code = subprocess.call(
["git", "commit", "-m", "Initial commit"], cwd=real_destination_dir)
if return_code == 0:
subprocess.call(["git", "status"], cwd=real_destination_dir)
if __name__ == '__main__':
main()