git-editlog 1.0.1__tar.gz → 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {git_editlog-1.0.1/git_editlog.egg-info → git_editlog-1.0.3}/PKG-INFO +1 -1
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/__init__.py +1 -1
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/__main__.py +34 -11
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/repo_watcher.py +57 -32
- {git_editlog-1.0.1 → git_editlog-1.0.3/git_editlog.egg-info}/PKG-INFO +1 -1
- {git_editlog-1.0.1 → git_editlog-1.0.3}/LICENSE +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/MANIFEST.in +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/README.md +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/pyinotify.py +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/pyinotify_watcher.py +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog/watchdog_watcher.py +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog.egg-info/SOURCES.txt +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog.egg-info/dependency_links.txt +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog.egg-info/entry_points.txt +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog.egg-info/requires.txt +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/git_editlog.egg-info/top_level.txt +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/pyproject.toml +0 -0
- {git_editlog-1.0.1 → git_editlog-1.0.3}/setup.cfg +0 -0
|
@@ -22,9 +22,36 @@ def setup_python_logging(verbose=False):
|
|
|
22
22
|
console_handler.setFormatter(log_formatter)
|
|
23
23
|
root.addHandler(console_handler)
|
|
24
24
|
|
|
25
|
+
|
|
26
|
+
def add_repo_list(fpath, repo_paths, seen_paths, limit):
|
|
27
|
+
cdir = fpath.parent
|
|
28
|
+
with fpath.open(encoding='utf8') as fp:
|
|
29
|
+
for line in fp:
|
|
30
|
+
line = line.strip()
|
|
31
|
+
if not line or line.startswith('#'):
|
|
32
|
+
continue
|
|
33
|
+
add_repo(cdir, line, repo_paths, seen_paths, limit - 1)
|
|
34
|
+
|
|
35
|
+
def add_repo(cdir, name, repo_paths, seen_paths, limit=10):
|
|
36
|
+
if is_list := name.startswith('@'):
|
|
37
|
+
name = name[1:].lstrip()
|
|
38
|
+
|
|
39
|
+
path = cdir / name
|
|
40
|
+
if path in seen_paths:
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
seen_paths.add(path)
|
|
44
|
+
|
|
45
|
+
if is_list:
|
|
46
|
+
if limit <= 0:
|
|
47
|
+
return
|
|
48
|
+
add_repo_list(path, repo_paths, seen_paths, limit)
|
|
49
|
+
else:
|
|
50
|
+
repo_paths.append(path)
|
|
51
|
+
|
|
25
52
|
def main():
|
|
26
53
|
p = argparse.ArgumentParser(description='')
|
|
27
|
-
p.add_argument('repos',
|
|
54
|
+
p.add_argument('repos', nargs='*')
|
|
28
55
|
p.add_argument('-l', '--repo-list', type=Path)
|
|
29
56
|
p.add_argument('-v', '--verbose', action='store_true', help='')
|
|
30
57
|
#p.add_argument(help='')
|
|
@@ -33,20 +60,16 @@ def main():
|
|
|
33
60
|
setup_python_logging(args.verbose)
|
|
34
61
|
|
|
35
62
|
repo_paths = []
|
|
63
|
+
seen_paths = set()
|
|
36
64
|
repo_watchers = []
|
|
65
|
+
|
|
66
|
+
cdir = Path('.')
|
|
67
|
+
|
|
37
68
|
for path in args.repos:
|
|
38
|
-
|
|
69
|
+
add_repo(cdir, path, repo_paths, seen_paths)
|
|
39
70
|
|
|
40
71
|
if args.repo_list:
|
|
41
|
-
|
|
42
|
-
with args.repo_list.open() as fp:
|
|
43
|
-
for line in fp:
|
|
44
|
-
line = line.strip()
|
|
45
|
-
if not line or line.startswith('#'):
|
|
46
|
-
continue
|
|
47
|
-
|
|
48
|
-
path = (base / line).absolute()
|
|
49
|
-
repo_paths.append(path)
|
|
72
|
+
add_repo_list(args.repo_list, repo_paths, seen_paths, 10)
|
|
50
73
|
|
|
51
74
|
for path in repo_paths:
|
|
52
75
|
try:
|
|
@@ -6,6 +6,7 @@ import argparse
|
|
|
6
6
|
import subprocess
|
|
7
7
|
import traceback
|
|
8
8
|
import logging
|
|
9
|
+
import threading
|
|
9
10
|
import copy
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
|
|
@@ -16,7 +17,7 @@ log = logging.getLogger(__name__)
|
|
|
16
17
|
EDITLOG_BRANCH = 'editlog'
|
|
17
18
|
EDITLOG_BASE_BRANCH = EDITLOG_BRANCH + '-base'
|
|
18
19
|
|
|
19
|
-
EXCLUDE_EXT = {'.3mf', '.stl', '.zip', '.jpg', '.jpeg', '.png'}
|
|
20
|
+
EXCLUDE_EXT = {'.3mf', '.stl', '.zip', '.jpg', '.jpeg', '.png', '.db', '.sqlite', '.sqlite-wal', '.sqlite-shm', '.sqlite-journal'}
|
|
20
21
|
|
|
21
22
|
def gitdir_allow_trigger(relpath):
|
|
22
23
|
if relpath == 'HEAD':
|
|
@@ -37,6 +38,8 @@ class BaseRepoWatcher:
|
|
|
37
38
|
self.git = git_helper.Git(repo_path)
|
|
38
39
|
self.repo_path = self.git.get_toplevel()
|
|
39
40
|
|
|
41
|
+
self.lock = threading.Lock()
|
|
42
|
+
|
|
40
43
|
info = self.git.run_capt(['rev-parse', '--show-toplevel', '--git-dir']).split('\n')
|
|
41
44
|
|
|
42
45
|
repo_path = self.repo_path = self.git.repo_path = Path(info[0]).absolute()
|
|
@@ -47,6 +50,7 @@ class BaseRepoWatcher:
|
|
|
47
50
|
|
|
48
51
|
self.editlog_dir = git_dir / 'editlog'
|
|
49
52
|
self.editlog_index = self.editlog_dir / 'index'
|
|
53
|
+
self.editlog_index_lock = self.editlog_dir / 'index.lock'
|
|
50
54
|
self.editlog_head_file = self.editlog_dir / 'HEAD'
|
|
51
55
|
|
|
52
56
|
self.git.env_vars['GIT_INDEX_FILE'] = str(self.editlog_index)
|
|
@@ -73,6 +77,9 @@ class BaseRepoWatcher:
|
|
|
73
77
|
self.editlog_branch_head = get_branch(self.git, EDITLOG_BRANCH)
|
|
74
78
|
self.last_head = get_branch(self.git, EDITLOG_BASE_BRANCH)
|
|
75
79
|
|
|
80
|
+
self.files_touched = set()
|
|
81
|
+
|
|
82
|
+
self.delete_lock()
|
|
76
83
|
if not self.editlog_branch_head:
|
|
77
84
|
# Create an empty tree to start with
|
|
78
85
|
empty_blob = self.git.run_capt(['hash-object', '-w', '-t', 'blob', '--stdin'], input=b'')
|
|
@@ -85,6 +92,12 @@ class BaseRepoWatcher:
|
|
|
85
92
|
|
|
86
93
|
self.setup_editlog_dir()
|
|
87
94
|
|
|
95
|
+
def delete_lock(self):
|
|
96
|
+
try:
|
|
97
|
+
os.unlink(self.editlog_index_lock)
|
|
98
|
+
except IOError:
|
|
99
|
+
pass
|
|
100
|
+
|
|
88
101
|
def setup_editlog_dir(self):
|
|
89
102
|
dir = self.editlog_dir
|
|
90
103
|
dir.mkdir(exist_ok=True)
|
|
@@ -102,52 +115,62 @@ class BaseRepoWatcher:
|
|
|
102
115
|
relpath = path.relative_to(self.git_dir)
|
|
103
116
|
if not gitdir_allow_trigger(str(relpath)):
|
|
104
117
|
return False
|
|
118
|
+
relpath = f'.git/{relpath}'
|
|
105
119
|
except ValueError: # path is not relative to gitdir
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return True
|
|
110
|
-
|
|
111
|
-
def should_check(self):
|
|
112
|
-
event_time = self.last_event_time
|
|
113
|
-
if self.last_check_event_time == event_time:
|
|
114
|
-
return False
|
|
115
|
-
|
|
116
|
-
ctime = time.time()
|
|
117
|
-
time_since_last_event = ctime - event_time
|
|
118
|
-
|
|
119
|
-
# Wait for idle of at least 3 seconds before checking
|
|
120
|
-
if time_since_last_event < 3:
|
|
121
|
-
# If this is the first time we've seen an event since the last check, note
|
|
122
|
-
# the time and return False.
|
|
123
|
-
if self.deferred_check_time is None:
|
|
124
|
-
self.deferred_check_time = event_time
|
|
120
|
+
try:
|
|
121
|
+
relpath = str(path.relative_to(self.repo_path))
|
|
122
|
+
except ValueError: # path is not relative to repo
|
|
125
123
|
return False
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return False
|
|
131
|
-
|
|
132
|
-
self.last_check_event_time = event_time
|
|
125
|
+
with self.lock:
|
|
126
|
+
self.last_event_time = time.time()
|
|
127
|
+
self.files_touched.add(relpath.replace('\\', '/'))
|
|
133
128
|
return True
|
|
134
129
|
|
|
135
130
|
def check(self):
|
|
136
131
|
if self.main_index_lock.exists():
|
|
137
132
|
return
|
|
138
133
|
|
|
139
|
-
|
|
140
|
-
|
|
134
|
+
with self.lock:
|
|
135
|
+
event_time = self.last_event_time
|
|
136
|
+
if self.last_check_event_time == event_time:
|
|
137
|
+
# No changes since the last check
|
|
138
|
+
return
|
|
141
139
|
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
ctime = time.time()
|
|
141
|
+
time_since_last_event = ctime - event_time
|
|
142
|
+
|
|
143
|
+
# Wait for idle of at least 5 seconds before checking.
|
|
144
|
+
if time_since_last_event < 5:
|
|
145
|
+
# If this is the first time we've seen an event since the last check, note
|
|
146
|
+
# the time and defer the check.
|
|
147
|
+
if self.deferred_check_time is None:
|
|
148
|
+
self.deferred_check_time = event_time
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
# If it's been less than 30 seconds after the first deferred check, continue to wait.
|
|
152
|
+
# Otherwise, continue and force a check.
|
|
153
|
+
if ctime < self.deferred_check_time + 30:
|
|
154
|
+
return
|
|
144
155
|
|
|
156
|
+
self.last_check_event_time = event_time
|
|
157
|
+
trigger_files = self.files_touched
|
|
158
|
+
self.files_touched = set()
|
|
159
|
+
|
|
160
|
+
print()
|
|
161
|
+
if trigger_files:
|
|
162
|
+
print(f'{self.repo_path}: changes detected in files:')
|
|
163
|
+
for path in sorted(trigger_files):
|
|
164
|
+
print(f' {path}')
|
|
165
|
+
print()
|
|
166
|
+
else:
|
|
167
|
+
print(f'{self.repo_path}: check forced')
|
|
145
168
|
|
|
146
169
|
if any(f.exists() for f in self.do_not_log_if_exists):
|
|
147
170
|
print(f'{self.repo_path}: rebase/merge in progress, not logging')
|
|
148
171
|
return
|
|
149
172
|
|
|
150
|
-
|
|
173
|
+
self.delete_lock()
|
|
151
174
|
|
|
152
175
|
# Force our head to be the head of the editlog branch so git status won't try to
|
|
153
176
|
# read the actual head
|
|
@@ -182,8 +205,10 @@ class BaseRepoWatcher:
|
|
|
182
205
|
|
|
183
206
|
tree_hash = self.git.run_capt(['write-tree'])
|
|
184
207
|
|
|
208
|
+
current_head = self.git.run_capt(['rev-parse', '--verify', 'HEAD'])
|
|
209
|
+
|
|
185
210
|
if (tree_hash == self.editlog_tree and current_head == self.last_head):
|
|
186
|
-
print(f'{self.repo_path}: no changes')
|
|
211
|
+
print(f'{self.repo_path}: no loggable changes')
|
|
187
212
|
return
|
|
188
213
|
|
|
189
214
|
ctime = time.time()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|