Avoid subprocess-writable temp file race condition · gitpython-developers/GitPython@9e5d0aa (original) (raw)

`@@ -6,7 +6,7 @@

`

6

6

`"""Module containing IndexFile, an Index implementation facilitating all kinds of index

`

7

7

`manipulations such as querying and merging."""

`

8

8

``

9

``

`-

from contextlib import ExitStack

`

``

9

`+

import contextlib

`

10

10

`import datetime

`

11

11

`import glob

`

12

12

`from io import BytesIO

`

67

67

`BinaryIO,

`

68

68

`Callable,

`

69

69

`Dict,

`

``

70

`+

Generator,

`

70

71

`IO,

`

71

72

`Iterable,

`

72

73

`Iterator,

`

96

97

`all = ("IndexFile", "CheckoutError", "StageType")

`

97

98

``

98

99

``

``

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

`+

if os.name == "nt":

`

``

110

`+

fd, name = tempfile.mkstemp(dir=directory)

`

``

111

`+

os.close(fd)

`

``

112

`+

try:

`

``

113

`+

yield name

`

``

114

`+

finally:

`

``

115

`+

os.remove(name)

`

``

116

`+

else:

`

``

117

`+

with tempfile.NamedTemporaryFile(dir=directory) as ctx:

`

``

118

`+

yield ctx.name

`

``

119

+

``

120

+

99

121

`class IndexFile(LazyMixin, git_diff.Diffable, Serializable):

`

100

122

`"""An Index that can be manipulated using a native implementation in order to save

`

101

123

` git command function calls wherever possible.

`

`@@ -359,11 +381,9 @@ def from_tree(cls, repo: "Repo", *treeish: Treeish, **kwargs: Any) -> "IndexFile

`

359

381

``

360

382

`# tmp file created in git home directory to be sure renaming

`

361

383

`# works - /tmp/ dirs could be on another device.

`

362

``

`-

with ExitStack() as stack:

`

363

``

`-

tmp_index = stack.enter_context(tempfile.NamedTemporaryFile(dir=repo.git_dir))

`

364

``

`-

if os.name == "nt":

`

365

``

`-

tmp_index.close()

`

366

``

`-

arg_list.append("--index-output=%s" % tmp_index.name)

`

``

384

`+

with contextlib.ExitStack() as stack:

`

``

385

`+

tmp_index = stack.enter_context(_named_temporary_file_for_subprocess(repo.git_dir))

`

``

386

`+

arg_list.append("--index-output=%s" % tmp_index)

`

367

387

`arg_list.extend(treeish)

`

368

388

``

369

389

`# 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

`

373

393

``

374

394

`stack.enter_context(TemporaryFileSwap(join_path_native(repo.git_dir, "index")))

`

375

395

`repo.git.read_tree(*arg_list, **kwargs)

`

376

``

`-

index = cls(repo, tmp_index.name)

`

``

396

`+

index = cls(repo, tmp_index)

`

377

397

`index.entries # Force it to read the file as we will delete the temp-file.

`

378

398

`return index

`

379

399

`# END index merge handling

`