Movatterモバイル変換


[0]ホーム

URL:


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

Commit9e5d0aa

Browse files
committed
Avoid subprocess-writable temp file race condition
This lets the Windows subprocess open or rename onto the temporaryfile using a more robust approach than inb12fd4a, avoiding therace condition described there, where the filename could beinadvertently reused between deletion and recreation of the file.This creates a context manager helper for the temporary index fileused in IndexFile.from_tree, whose implementation differs byoperating system:- Delegating straightforwardly to NamedTempoaryFile on POSIX systems where an open file can replaced by having another file renamed to it (just as it can be deleted).- Employing custom logic on Windows, using mkstemp, closing the temporary file without immediately deleting it (so it won't be reused by any process seeking to create a temporary file), and then deleting it on context manager exit.IndexFile.from_tree now calls this helper instead ofNamedTemporaryFile. For convenience, the helper provides the path,i.e. the "name", when entered, so tmp_index is now just that path.(At least for now, this helper is implemented as a nonpublicfunction in the git.index.base module, rather than in thegit.index.util module. If it were public in git.index.util like theother facilities there, then some later changes to it, or its laterremoval, would be a breaking change to GitPython. If it werenonpublic in git.index.util, then this would not be a concern, butit would be unintuitive for it to be accessed from code in thegit.index.base module. In the future, one way to address this mightbe to have one or more nonpublic _util modules with public members.Because it would still be a breaking change to drop existing publicutil modules, that would be more utility modules in total, so sucha change isn't included here just for this one used-once function.)
1 parent928ca1e commit9e5d0aa

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

‎git/index/base.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""Module containing IndexFile, an Index implementation facilitating all kinds of index
77
manipulations such as querying and merging."""
88

9-
fromcontextlibimportExitStack
9+
importcontextlib
1010
importdatetime
1111
importglob
1212
fromioimportBytesIO
@@ -67,6 +67,7 @@
6767
BinaryIO,
6868
Callable,
6969
Dict,
70+
Generator,
7071
IO,
7172
Iterable,
7273
Iterator,
@@ -96,6 +97,27 @@
9697
__all__= ("IndexFile","CheckoutError","StageType")
9798

9899

100+
@contextlib.contextmanager
101+
def_named_temporary_file_for_subprocess(directory:PathLike)->Generator[str,None,None]:
102+
"""Create a named temporary file git subprocesses can open, deleting it afterward.
103+
104+
:param directory: The directory in which the file is created.
105+
106+
:return: A context manager object that creates the file and provides its name on
107+
entry, and deletes it on exit.
108+
"""
109+
ifos.name=="nt":
110+
fd,name=tempfile.mkstemp(dir=directory)
111+
os.close(fd)
112+
try:
113+
yieldname
114+
finally:
115+
os.remove(name)
116+
else:
117+
withtempfile.NamedTemporaryFile(dir=directory)asctx:
118+
yieldctx.name
119+
120+
99121
classIndexFile(LazyMixin,git_diff.Diffable,Serializable):
100122
"""An Index that can be manipulated using a native implementation in order to save
101123
git command function calls wherever possible.
@@ -359,11 +381,9 @@ def from_tree(cls, repo: "Repo", *treeish: Treeish, **kwargs: Any) -> "IndexFile
359381

360382
# tmp file created in git home directory to be sure renaming
361383
# works - /tmp/ dirs could be on another device.
362-
withExitStack()asstack:
363-
tmp_index=stack.enter_context(tempfile.NamedTemporaryFile(dir=repo.git_dir))
364-
ifos.name=="nt":
365-
tmp_index.close()
366-
arg_list.append("--index-output=%s"%tmp_index.name)
384+
withcontextlib.ExitStack()asstack:
385+
tmp_index=stack.enter_context(_named_temporary_file_for_subprocess(repo.git_dir))
386+
arg_list.append("--index-output=%s"%tmp_index)
367387
arg_list.extend(treeish)
368388

369389
# Move current index out of the way - otherwise the merge may fail
@@ -373,7 +393,7 @@ def from_tree(cls, repo: "Repo", *treeish: Treeish, **kwargs: Any) -> "IndexFile
373393

374394
stack.enter_context(TemporaryFileSwap(join_path_native(repo.git_dir,"index")))
375395
repo.git.read_tree(*arg_list,**kwargs)
376-
index=cls(repo,tmp_index.name)
396+
index=cls(repo,tmp_index)
377397
index.entries# Force it to read the file as we will delete the temp-file.
378398
returnindex
379399
# END index merge handling

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp