summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--git_config.py7
-rw-r--r--manifest_xml.py3
-rw-r--r--platform_utils.py31
-rw-r--r--project.py20
-rw-r--r--subcmds/sync.py20
-rw-r--r--tests/test_platform_utils.py50
6 files changed, 80 insertions, 51 deletions
diff --git a/git_config.py b/git_config.py
index 778e81a4..bc70d160 100644
--- a/git_config.py
+++ b/git_config.py
@@ -352,8 +352,8 @@ class GitConfig(object):
352 Trace(': parsing %s', self.file) 352 Trace(': parsing %s', self.file)
353 with open(self._json) as fd: 353 with open(self._json) as fd:
354 return json.load(fd) 354 return json.load(fd)
355 except (IOError, ValueError): 355 except (IOError, ValueErrorl):
356 platform_utils.remove(self._json) 356 platform_utils.remove(self._json, missing_ok=True)
357 return None 357 return None
358 358
359 def _SaveJson(self, cache): 359 def _SaveJson(self, cache):
@@ -361,8 +361,7 @@ class GitConfig(object):
361 with open(self._json, 'w') as fd: 361 with open(self._json, 'w') as fd:
362 json.dump(cache, fd, indent=2) 362 json.dump(cache, fd, indent=2)
363 except (IOError, TypeError): 363 except (IOError, TypeError):
364 if os.path.exists(self._json): 364 platform_utils.remove(self._json, missing_ok=True)
365 platform_utils.remove(self._json)
366 365
367 def _ReadGit(self): 366 def _ReadGit(self):
368 """ 367 """
diff --git a/manifest_xml.py b/manifest_xml.py
index 135c91fb..86f20202 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -270,8 +270,7 @@ class XmlManifest(object):
270 self.Override(name) 270 self.Override(name)
271 271
272 # Old versions of repo would generate symlinks we need to clean up. 272 # Old versions of repo would generate symlinks we need to clean up.
273 if os.path.lexists(self.manifestFile): 273 platform_utils.remove(self.manifestFile, missing_ok=True)
274 platform_utils.remove(self.manifestFile)
275 # This file is interpreted as if it existed inside the manifest repo. 274 # This file is interpreted as if it existed inside the manifest repo.
276 # That allows us to use <include> with the relative file name. 275 # That allows us to use <include> with the relative file name.
277 with open(self.manifestFile, 'w') as fp: 276 with open(self.manifestFile, 'w') as fp:
diff --git a/platform_utils.py b/platform_utils.py
index 5741f4d3..0203249a 100644
--- a/platform_utils.py
+++ b/platform_utils.py
@@ -127,28 +127,27 @@ def rename(src, dst):
127 shutil.move(src, dst) 127 shutil.move(src, dst)
128 128
129 129
130def remove(path): 130def remove(path, missing_ok=False):
131 """Remove (delete) the file path. This is a replacement for os.remove that 131 """Remove (delete) the file path. This is a replacement for os.remove that
132 allows deleting read-only files on Windows, with support for long paths and 132 allows deleting read-only files on Windows, with support for long paths and
133 for deleting directory symbolic links. 133 for deleting directory symbolic links.
134 134
135 Availability: Unix, Windows.""" 135 Availability: Unix, Windows."""
136 if isWindows(): 136 longpath = _makelongpath(path) if isWindows() else path
137 longpath = _makelongpath(path) 137 try:
138 try: 138 os.remove(longpath)
139 os.remove(longpath) 139 except OSError as e:
140 except OSError as e: 140 if e.errno == errno.EACCES:
141 if e.errno == errno.EACCES: 141 os.chmod(longpath, stat.S_IWRITE)
142 os.chmod(longpath, stat.S_IWRITE) 142 # Directory symbolic links must be deleted with 'rmdir'.
143 # Directory symbolic links must be deleted with 'rmdir'. 143 if islink(longpath) and isdir(longpath):
144 if islink(longpath) and isdir(longpath): 144 os.rmdir(longpath)
145 os.rmdir(longpath)
146 else:
147 os.remove(longpath)
148 else: 145 else:
149 raise 146 os.remove(longpath)
150 else: 147 elif missing_ok and e.errno == errno.ENOENT:
151 os.remove(path) 148 pass
149 else:
150 raise
152 151
153 152
154def walk(top, topdown=True, onerror=None, followlinks=False): 153def walk(top, topdown=True, onerror=None, followlinks=False):
diff --git a/project.py b/project.py
index fe88a505..634d88c5 100644
--- a/project.py
+++ b/project.py
@@ -1182,10 +1182,8 @@ class Project(object):
1182 self._InitMRef() 1182 self._InitMRef()
1183 else: 1183 else:
1184 self._InitMirrorHead() 1184 self._InitMirrorHead()
1185 try: 1185 platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD'),
1186 platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD')) 1186 missing_ok=True)
1187 except OSError:
1188 pass
1189 return True 1187 return True
1190 1188
1191 def PostRepoUpgrade(self): 1189 def PostRepoUpgrade(self):
@@ -2307,15 +2305,12 @@ class Project(object):
2307 cmd.append('+refs/tags/*:refs/tags/*') 2305 cmd.append('+refs/tags/*:refs/tags/*')
2308 2306
2309 ok = GitCommand(self, cmd, bare=True).Wait() == 0 2307 ok = GitCommand(self, cmd, bare=True).Wait() == 0
2310 if os.path.exists(bundle_dst): 2308 platform_utils.remove(bundle_dst, missing_ok=True)
2311 platform_utils.remove(bundle_dst) 2309 platform_utils.remove(bundle_tmp, missing_ok=True)
2312 if os.path.exists(bundle_tmp):
2313 platform_utils.remove(bundle_tmp)
2314 return ok 2310 return ok
2315 2311
2316 def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet, verbose): 2312 def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet, verbose):
2317 if os.path.exists(dstPath): 2313 platform_utils.remove(dstPath, missing_ok=True)
2318 platform_utils.remove(dstPath)
2319 2314
2320 cmd = ['curl', '--fail', '--output', tmpPath, '--netrc', '--location'] 2315 cmd = ['curl', '--fail', '--output', tmpPath, '--netrc', '--location']
2321 if quiet: 2316 if quiet:
@@ -2739,10 +2734,7 @@ class Project(object):
2739 # If the source file doesn't exist, ensure the destination 2734 # If the source file doesn't exist, ensure the destination
2740 # file doesn't either. 2735 # file doesn't either.
2741 if name in symlink_files and not os.path.lexists(src): 2736 if name in symlink_files and not os.path.lexists(src):
2742 try: 2737 platform_utils.remove(dst, missing_ok=True)
2743 platform_utils.remove(dst)
2744 except OSError:
2745 pass
2746 2738
2747 except OSError as e: 2739 except OSError as e:
2748 if e.errno == errno.EPERM: 2740 if e.errno == errno.EPERM:
diff --git a/subcmds/sync.py b/subcmds/sync.py
index c99b06ca..3211cbb1 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -767,13 +767,9 @@ later is required to fix a server side protocol bug.
767 set(new_copyfile_paths)) 767 set(new_copyfile_paths))
768 768
769 for need_remove_file in need_remove_files: 769 for need_remove_file in need_remove_files:
770 try: 770 # Try to remove the updated copyfile or linkfile.
771 platform_utils.remove(need_remove_file) 771 # So, if the file is not exist, nothing need to do.
772 except OSError as e: 772 platform_utils.remove(need_remove_file, missing_ok=True)
773 if e.errno == errno.ENOENT:
774 # Try to remove the updated copyfile or linkfile.
775 # So, if the file is not exist, nothing need to do.
776 pass
777 773
778 # Create copy-link-files.json, save dest path of "copyfile" and "linkfile". 774 # Create copy-link-files.json, save dest path of "copyfile" and "linkfile".
779 with open(copylinkfile_path, 'w', encoding='utf-8') as fp: 775 with open(copylinkfile_path, 'w', encoding='utf-8') as fp:
@@ -1171,10 +1167,7 @@ class _FetchTimes(object):
1171 with open(self._path) as f: 1167 with open(self._path) as f:
1172 self._times = json.load(f) 1168 self._times = json.load(f)
1173 except (IOError, ValueError): 1169 except (IOError, ValueError):
1174 try: 1170 platform_utils.remove(self._path, missing_ok=True)
1175 platform_utils.remove(self._path)
1176 except OSError:
1177 pass
1178 self._times = {} 1171 self._times = {}
1179 1172
1180 def Save(self): 1173 def Save(self):
@@ -1192,10 +1185,7 @@ class _FetchTimes(object):
1192 with open(self._path, 'w') as f: 1185 with open(self._path, 'w') as f:
1193 json.dump(self._times, f, indent=2) 1186 json.dump(self._times, f, indent=2)
1194 except (IOError, TypeError): 1187 except (IOError, TypeError):
1195 try: 1188 platform_utils.remove(self._path, missing_ok=True)
1196 platform_utils.remove(self._path)
1197 except OSError:
1198 pass
1199 1189
1200# This is a replacement for xmlrpc.client.Transport using urllib2 1190# This is a replacement for xmlrpc.client.Transport using urllib2
1201# and supporting persistent-http[s]. It cannot change hosts from 1191# and supporting persistent-http[s]. It cannot change hosts from
diff --git a/tests/test_platform_utils.py b/tests/test_platform_utils.py
new file mode 100644
index 00000000..55b7805c
--- /dev/null
+++ b/tests/test_platform_utils.py
@@ -0,0 +1,50 @@
1# Copyright 2021 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Unittests for the platform_utils.py module."""
16
17import os
18import tempfile
19import unittest
20
21import platform_utils
22
23
24class RemoveTests(unittest.TestCase):
25 """Check remove() helper."""
26
27 def testMissingOk(self):
28 """Check missing_ok handling."""
29 with tempfile.TemporaryDirectory() as tmpdir:
30 path = os.path.join(tmpdir, 'test')
31
32 # Should not fail.
33 platform_utils.remove(path, missing_ok=True)
34
35 # Should fail.
36 self.assertRaises(OSError, platform_utils.remove, path)
37 self.assertRaises(OSError, platform_utils.remove, path, missing_ok=False)
38
39 # Should not fail if it exists.
40 open(path, 'w').close()
41 platform_utils.remove(path, missing_ok=True)
42 self.assertFalse(os.path.exists(path))
43
44 open(path, 'w').close()
45 platform_utils.remove(path)
46 self.assertFalse(os.path.exists(path))
47
48 open(path, 'w').close()
49 platform_utils.remove(path, missing_ok=False)
50 self.assertFalse(os.path.exists(path))