Dulwich.io dulwich / 88562d7
Merge support for hiding .git directories on Windows. Fixes #585. Jelmer Vernooń≥ a month ago
3 changed file(s) with 68 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1010 C Git. (Boris Feld)
1111
1212 * Return a 404 not found error when repository is not found.
13
14 * Mark ``.git`` directories as hidden on Windows.
15 (Martin Packman, #585)
1316
1417 0.19.11 2019-02-07
1518
240240 else:
241241 graft_lines.append(commit)
242242 return b'\n'.join(graft_lines)
243
244
245 def _set_filesystem_hidden(path):
246 """Mark path as to be hidden if supported by platform and filesystem.
247
248 On win32 uses SetFileAttributesW api:
249 <https://docs.microsoft.com/windows/desktop/api/fileapi/nf-fileapi-setfileattributesw>
250 """
251 if sys.platform == 'win32':
252 import ctypes
253 from ctypes.wintypes import BOOL, DWORD, LPCWSTR
254
255 FILE_ATTRIBUTE_HIDDEN = 2
256 SetFileAttributesW = ctypes.WINFUNCTYPE(BOOL, LPCWSTR, DWORD)(
257 ("SetFileAttributesW", ctypes.windll.kernel32))
258
259 if isinstance(path, bytes):
260 path = path.decode(sys.getfilesystemencoding())
261 if not SetFileAttributesW(path, FILE_ATTRIBUTE_HIDDEN):
262 pass # Could raise or log `ctypes.WinError()` here
263
264 # Could implement other platform specific filesytem hiding here
243265
244266
245267 class BaseRepo(object):
12331255 os.mkdir(path)
12341256 controldir = os.path.join(path, CONTROLDIR)
12351257 os.mkdir(controldir)
1258 _set_filesystem_hidden(controldir)
12361259 cls._init_maybe_bare(controldir, False)
12371260 return cls(path)
12381261
264264 [e.commit.id for e in
265265 r.get_walker(b'2a72d929692c41d8554c07f6301757ba18a65d91')],
266266 [b'2a72d929692c41d8554c07f6301757ba18a65d91'])
267
268 def assertFilesystemHidden(self, path):
269 if sys.platform != 'win32':
270 return
271 import ctypes
272 from ctypes.wintypes import DWORD, LPCWSTR
273 GetFileAttributesW = ctypes.WINFUNCTYPE(DWORD, LPCWSTR)(
274 ('GetFileAttributesW', ctypes.windll.kernel32))
275 self.assertTrue(2 & GetFileAttributesW(path))
276
277 def test_init_existing(self):
278 tmp_dir = self.mkdtemp()
279 self.addCleanup(shutil.rmtree, tmp_dir)
280 t = Repo.init(tmp_dir)
281 self.addCleanup(t.close)
282 self.assertEqual(os.listdir(tmp_dir), ['.git'])
283 self.assertFilesystemHidden(os.path.join(tmp_dir, '.git'))
284
285 def test_init_mkdir(self):
286 tmp_dir = self.mkdtemp()
287 self.addCleanup(shutil.rmtree, tmp_dir)
288 repo_dir = os.path.join(tmp_dir, 'a-repo')
289
290 t = Repo.init(repo_dir, mkdir=True)
291 self.addCleanup(t.close)
292 self.assertEqual(os.listdir(repo_dir), ['.git'])
293 self.assertFilesystemHidden(os.path.join(repo_dir, '.git'))
294
295 def test_init_mkdir_unicode(self):
296 repo_name = u'\xa7'
297 try:
298 repo_name.encode(sys.getfilesystemencoding())
299 except UnicodeEncodeError:
300 self.skipTest('filesystem lacks unicode support')
301 tmp_dir = self.mkdtemp()
302 self.addCleanup(shutil.rmtree, tmp_dir)
303 repo_dir = os.path.join(tmp_dir, repo_name)
304
305 t = Repo.init(repo_dir, mkdir=True)
306 self.addCleanup(t.close)
307 self.assertEqual(os.listdir(repo_dir), ['.git'])
308 self.assertFilesystemHidden(os.path.join(repo_dir, '.git'))
267309
268310 @skipIf(sys.platform == 'win32', 'fails on Windows')
269311 def test_fetch(self):