Skip to content

Commit b526dda

Browse files
committed
Merge branch 'mr/fs' into 'master'
Improve sync_tree performance See merge request it/e3-core!399
2 parents da10595 + fa1d361 commit b526dda

4 files changed

Lines changed: 665 additions & 183 deletions

File tree

src/e3/anod/checkout.py

Lines changed: 43 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212

1313
import e3.log
1414
from e3.anod.status import ReturnValue
15-
from e3.fs import VCS_IGNORE_LIST, get_filetree_state, rm, sync_tree
16-
from e3.os.fs import unixpath, which
17-
from e3.os.process import PIPE, Run
15+
from e3.fs import get_filetree_state, rm, sync_tree
16+
from e3.os.process import PIPE
1817
from e3.vcs.git import GitError, GitRepository
1918
from e3.vcs.svn import SVNError, SVNRepository
2019

@@ -125,72 +124,47 @@ def update_external(
125124
old_commit = ""
126125
ignore_list: list[str] = []
127126

128-
if which("rsync") and "use-rsync" in os.environ.get(
129-
"E3_ENABLE_FEATURE", ""
130-
).split(","):
131-
# Run rsync using -a but without preserving timestamps. --update switch
132-
# is also used to skip files that are older in the user directory than
133-
# in the checkout itself. This ensure rsync remain efficient event when
134-
# timestamps are not preserved (otherwise rsync has to compute checksum
135-
# of all file as quick check cannot be used when timestamp is not
136-
# preserved).
137-
rsync_cmd = [
138-
"rsync",
139-
"--update",
140-
"-rlpgoD",
141-
f"{unixpath(url)}/",
142-
f"{unixpath(self.working_dir)}",
143-
"--delete-excluded",
144-
] + [f"--exclude={el}" for el in VCS_IGNORE_LIST]
145-
146-
if Path(url, ".git").is_dir() and Path(url, ".gitignore").is_file():
147-
rsync_cmd.append("--filter=:- .gitignore")
148-
149-
p = Run(rsync_cmd, cwd=url, output=None)
150-
if p.status != 0:
151-
msg = "rsync failed"
152-
raise e3.error.E3Error(msg)
153-
else:
154-
# Test for a git repository by looking for ".git" in the current
155-
# directory - either as a file or as a directory. We check both
156-
# because, if a normal git clone, ".git" is a directory; if a
157-
# git clone with `git submodule init`, ".git" is a file.
158-
if Path(url, ".git").exists():
159-
# It seems that this is a git repository. Get the list of files to
160-
# ignore
161-
try:
162-
g = GitRepository(working_tree=url)
163-
ignore_list_lines = g.git_cmd(
164-
[
165-
"ls-files",
166-
"-o",
167-
"--ignored",
168-
"--exclude-standard",
169-
"--directory",
170-
],
171-
output=PIPE,
172-
).out
173-
174-
ignore_list = (
175-
[]
176-
if ignore_list_lines is None
177-
else [
178-
f"/{f.strip().rstrip('/')}"
179-
for f in ignore_list_lines.splitlines()
180-
]
181-
)
182-
logger.debug("Ignore in external: %s", ignore_list)
183-
except Exception: # defensive code # noqa: BLE001, S110
184-
# don't crash on exception
185-
pass
186-
187-
sync_tree(
188-
url,
189-
self.working_dir,
190-
preserve_timestamps=False,
191-
delete_ignore=True,
192-
ignore=[".git", ".svn", *ignore_list],
193-
)
127+
# Test for a git repository by looking for ".git" in the current
128+
# directory - either as a file or as a directory. We check both
129+
# because, if a normal git clone, ".git" is a directory; if a
130+
# git clone with `git submodule init`, ".git" is a file.
131+
if Path(url, ".git").exists():
132+
# It seems that this is a git repository. Get the list of files to
133+
# ignore
134+
try:
135+
g = GitRepository(working_tree=url)
136+
ignore_list_lines = g.git_cmd(
137+
[
138+
"ls-files",
139+
# Show other (i.e. untracked) files in the output
140+
"--others",
141+
"--ignored",
142+
"--exclude-standard",
143+
"--directory",
144+
],
145+
output=PIPE,
146+
).out
147+
148+
ignore_list = (
149+
[]
150+
if ignore_list_lines is None
151+
else [
152+
f"/{f.strip().rstrip('/')}"
153+
for f in ignore_list_lines.splitlines()
154+
]
155+
)
156+
logger.debug("Ignore in external: %s", ignore_list)
157+
except Exception: # defensive code # noqa: BLE001, S110
158+
# don't crash on exception
159+
pass
160+
161+
sync_tree(
162+
url,
163+
self.working_dir,
164+
preserve_timestamps=False,
165+
delete_ignore=True,
166+
ignore=[".git", ".svn", *ignore_list],
167+
)
194168

195169
new_commit = get_filetree_state(self.working_dir, ignore_hidden=False)
196170
if new_commit == old_commit:

0 commit comments

Comments
 (0)