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

Commita30b3b7

Browse files
authored
Merge pull request#1751 from EliahKagan/fromtree
Fix IndexFile.from_tree on Windows
2 parents3dbf5b3 +782c062 commita30b3b7

File tree

6 files changed

+51
-88
lines changed

6 files changed

+51
-88
lines changed

‎AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ Contributors are:
5252
-Joseph Hale <me _at_ jhale.dev>
5353
-Santos Gallegos <stsewd _at_ proton.me>
5454
-Wenhan Zhu <wzhu.cosmos _at_ gmail.com>
55+
-Eliah Kagan <eliah.kagan _at_ gmail.com>
5556

5657
Portions derived from other open source works and are clearly marked.

‎git/index/base.py

Lines changed: 30 additions & 8 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,10 +97,30 @@
9697
__all__= ("IndexFile","CheckoutError","StageType")
9798

9899

99-
classIndexFile(LazyMixin,git_diff.Diffable,Serializable):
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.
100108
"""
101-
An Index that can be manipulated using a native implementation in order to save git
102-
command function calls wherever possible.
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+
121+
classIndexFile(LazyMixin,git_diff.Diffable,Serializable):
122+
"""An Index that can be manipulated using a native implementation in order to save
123+
git command function calls wherever possible.
103124
104125
This provides custom merging facilities allowing to merge without actually changing
105126
your index or your working tree. This way you can perform own test-merges based
@@ -360,9 +381,9 @@ def from_tree(cls, repo: "Repo", *treeish: Treeish, **kwargs: Any) -> "IndexFile
360381

361382
# tmp file created in git home directory to be sure renaming
362383
# works - /tmp/ dirs could be on another device.
363-
withExitStack()asstack:
364-
tmp_index=stack.enter_context(tempfile.NamedTemporaryFile(dir=repo.git_dir))
365-
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)
366387
arg_list.extend(treeish)
367388

368389
# Move current index out of the way - otherwise the merge may fail
@@ -372,12 +393,13 @@ def from_tree(cls, repo: "Repo", *treeish: Treeish, **kwargs: Any) -> "IndexFile
372393

373394
stack.enter_context(TemporaryFileSwap(join_path_native(repo.git_dir,"index")))
374395
repo.git.read_tree(*arg_list,**kwargs)
375-
index=cls(repo,tmp_index.name)
396+
index=cls(repo,tmp_index)
376397
index.entries# Force it to read the file as we will delete the temp-file.
377398
returnindex
378399
# END index merge handling
379400

380401
# UTILITIES
402+
381403
@unbare_repo
382404
def_iter_expand_paths(self:"IndexFile",paths:Sequence[PathLike])->Iterator[PathLike]:
383405
"""Expand the directories in list of paths to the corresponding paths accordingly.

‎test/test_docs.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
importpytest
1010

11-
fromgit.excimportGitCommandError
1211
fromtest.libimportTestBase
1312
fromtest.lib.helperimportwith_rw_directory
1413

14+
importos.path
15+
1516

1617
classTutorials(TestBase):
1718
deftearDown(self):
@@ -206,14 +207,6 @@ def update(self, op_code, cur_count, max_count=None, message=""):
206207
assertsm.module_exists()# The submodule's working tree was checked out by update.
207208
# ![14-test_init_repo_object]
208209

209-
@pytest.mark.xfail(
210-
os.name=="nt",
211-
reason=(
212-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
213-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
214-
),
215-
raises=GitCommandError,
216-
)
217210
@with_rw_directory
218211
deftest_references_and_objects(self,rw_dir):
219212
# [1-test_references_and_objects]

‎test/test_fun.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33

44
fromioimportBytesIO
55
fromstatimportS_IFDIR,S_IFREG,S_IFLNK,S_IXUSR
6-
importos
6+
fromosimportstat
77
importos.pathasosp
88

9-
importpytest
10-
119
fromgitimportGit
12-
fromgit.excimportGitCommandError
1310
fromgit.indeximportIndexFile
1411
fromgit.index.funimport (
1512
aggressive_tree_merge,
@@ -37,14 +34,6 @@ def _assert_index_entries(self, entries, trees):
3734
assert (entry.path,entry.stage)inindex.entries
3835
# END assert entry matches fully
3936

40-
@pytest.mark.xfail(
41-
os.name=="nt",
42-
reason=(
43-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
44-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
45-
),
46-
raises=GitCommandError,
47-
)
4837
deftest_aggressive_tree_merge(self):
4938
# Head tree with additions, removals and modification compared to its predecessor.
5039
odb=self.rorepo.odb
@@ -302,12 +291,12 @@ def test_linked_worktree_traversal(self, rw_dir):
302291
rw_master.git.worktree("add",worktree_path,branch.name)
303292

304293
dotgit=osp.join(worktree_path,".git")
305-
statbuf=os.stat(dotgit)
294+
statbuf=stat(dotgit)
306295
self.assertTrue(statbuf.st_mode&S_IFREG)
307296

308297
gitdir=find_worktree_git_dir(dotgit)
309298
self.assertIsNotNone(gitdir)
310-
statbuf=os.stat(gitdir)
299+
statbuf=stat(gitdir)
311300
self.assertTrue(statbuf.st_mode&S_IFDIR)
312301

313302
deftest_tree_entries_from_data_with_failing_name_decode_py3(self):

‎test/test_index.py

Lines changed: 15 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,21 @@
1717
fromsumtypesimportconstructor,sumtype
1818

1919
fromgitimport (
20+
BlobFilter,
21+
Diff,
22+
Git,
2023
IndexFile,
24+
Object,
2125
Repo,
22-
BlobFilter,
23-
UnmergedEntriesError,
2426
Tree,
25-
Object,
26-
Diff,
27-
GitCommandError,
27+
)
28+
fromgit.excimport (
2829
CheckoutError,
30+
GitCommandError,
31+
HookExecutionError,
32+
InvalidGitRepositoryError,
33+
UnmergedEntriesError,
2934
)
30-
fromgit.excimportHookExecutionError,InvalidGitRepositoryError
3135
fromgit.index.funimporthook_path
3236
fromgit.index.typimportBaseIndexEntry,IndexEntry
3337
fromgit.objectsimportBlob
@@ -284,14 +288,6 @@ def add_bad_blob():
284288
exceptExceptionasex:
285289
assert"index.lock' could not be obtained"notinstr(ex)
286290

287-
@pytest.mark.xfail(
288-
os.name=="nt",
289-
reason=(
290-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
291-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
292-
),
293-
raises=GitCommandError,
294-
)
295291
@with_rw_repo("0.1.6")
296292
deftest_index_file_from_tree(self,rw_repo):
297293
common_ancestor_sha="5117c9c8a4d3af19a9958677e45cda9269de1541"
@@ -342,14 +338,6 @@ def test_index_file_from_tree(self, rw_repo):
342338
# END for each blob
343339
self.assertEqual(num_blobs,len(three_way_index.entries))
344340

345-
@pytest.mark.xfail(
346-
os.name=="nt",
347-
reason=(
348-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
349-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
350-
),
351-
raises=GitCommandError,
352-
)
353341
@with_rw_repo("0.1.6")
354342
deftest_index_merge_tree(self,rw_repo):
355343
# A bit out of place, but we need a different repo for this:
@@ -412,14 +400,6 @@ def test_index_merge_tree(self, rw_repo):
412400
self.assertEqual(len(unmerged_blobs),1)
413401
self.assertEqual(list(unmerged_blobs.keys())[0],manifest_key[0])
414402

415-
@pytest.mark.xfail(
416-
os.name=="nt",
417-
reason=(
418-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
419-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
420-
),
421-
raises=GitCommandError,
422-
)
423403
@with_rw_repo("0.1.6")
424404
deftest_index_file_diffing(self,rw_repo):
425405
# Default Index instance points to our index.
@@ -555,12 +535,9 @@ def _count_existing(self, repo, files):
555535
# END num existing helper
556536

557537
@pytest.mark.xfail(
558-
os.name=="nt",
559-
reason=(
560-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
561-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
562-
),
563-
raises=GitCommandError,
538+
os.name=="nt"andGit().config("core.symlinks")=="true",
539+
reason="Assumes symlinks are not created on Windows and opens a symlink to a nonexistent target.",
540+
raises=FileNotFoundError,
564541
)
565542
@with_rw_repo("0.1.6")
566543
deftest_index_mutation(self,rw_repo):
@@ -772,7 +749,7 @@ def mixed_iterator():
772749
# END for each target
773750
# END real symlink test
774751

775-
# Add fake symlink and assure it checks-our as symlink.
752+
# Add fake symlink and assure it checks out as a symlink.
776753
fake_symlink_relapath="my_fake_symlink"
777754
link_target="/etc/that"
778755
fake_symlink_path=self._make_file(fake_symlink_relapath,link_target,rw_repo)
@@ -806,7 +783,7 @@ def mixed_iterator():
806783
os.remove(fake_symlink_path)
807784
index.checkout(fake_symlink_path)
808785

809-
# On Windows, we will never get symlinks.
786+
# On Windows, wecurrently assume wewill never get symlinks.
810787
ifos.name=="nt":
811788
# Symlinks should contain the link as text (which is what a
812789
# symlink actually is).
@@ -915,14 +892,6 @@ def make_paths():
915892
forabsfileinabsfiles:
916893
assertosp.isfile(absfile)
917894

918-
@pytest.mark.xfail(
919-
os.name=="nt",
920-
reason=(
921-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
922-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
923-
),
924-
raises=GitCommandError,
925-
)
926895
@with_rw_repo("HEAD")
927896
deftest_compare_write_tree(self,rw_repo):
928897
"""Test writing all trees, comparing them for equality."""

‎test/test_refs.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
55

66
fromitertoolsimportchain
7-
importos
87
frompathlibimportPath
98

10-
importpytest
11-
129
fromgitimport (
1310
Reference,
1411
Head,
@@ -218,14 +215,6 @@ def test_head_checkout_detached_head(self, rw_repo):
218215
assertisinstance(res,SymbolicReference)
219216
assertres.name=="HEAD"
220217

221-
@pytest.mark.xfail(
222-
os.name=="nt",
223-
reason=(
224-
"IndexFile.from_tree is broken on Windows (related to NamedTemporaryFile), see #1630.\n"
225-
"'git read-tree --index-output=...' fails with 'fatal: unable to write new index file'."
226-
),
227-
raises=GitCommandError,
228-
)
229218
@with_rw_repo("0.1.6")
230219
deftest_head_reset(self,rw_repo):
231220
cur_head=rw_repo.head

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp