use open context managers in more places

Use open() as a context manager to simplify the close logic and make
the code easier to read & understand.  This is also more Pythonic.

Change-Id: I579d03cca86f99b2c6c6a1f557f6e5704e2515a7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/244734
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
diff --git a/editor.py b/editor.py
index b761eb5..19b96c3 100644
--- a/editor.py
+++ b/editor.py
@@ -106,11 +106,8 @@
         raise EditorError('editor failed with exit status %d: %s %s'
           % (rc, editor, path))
 
-      fd2 = open(path)
-      try:
+      with open(path) as fd2:
         return fd2.read()
-      finally:
-        fd2.close()
     finally:
       if fd:
         os.close(fd)
diff --git a/git_config.py b/git_config.py
index 1ea9c43..680de90 100644
--- a/git_config.py
+++ b/git_config.py
@@ -276,22 +276,16 @@
       return None
     try:
       Trace(': parsing %s', self.file)
-      fd = open(self._json)
-      try:
+      with open(self._json) as fd:
         return json.load(fd)
-      finally:
-        fd.close()
     except (IOError, ValueError):
       platform_utils.remove(self._json)
       return None
 
   def _SaveJson(self, cache):
     try:
-      fd = open(self._json, 'w')
-      try:
+      with open(self._json, 'w') as fd:
         json.dump(cache, fd, indent=2)
-      finally:
-        fd.close()
     except (IOError, TypeError):
       if os.path.exists(self._json):
         platform_utils.remove(self._json)
@@ -773,15 +767,12 @@
       self._Set('merge', self.merge)
 
     else:
-      fd = open(self._config.file, 'a')
-      try:
+      with open(self._config.file, 'a') as fd:
         fd.write('[branch "%s"]\n' % self.name)
         if self.remote:
           fd.write('\tremote = %s\n' % self.remote.name)
         if self.merge:
           fd.write('\tmerge = %s\n' % self.merge)
-      finally:
-        fd.close()
 
   def _Set(self, key, value):
     key = 'branch.%s.%s' % (self.name, key)
diff --git a/git_refs.py b/git_refs.py
index 98ed1e2..debd4cb 100644
--- a/git_refs.py
+++ b/git_refs.py
@@ -141,18 +141,11 @@
 
   def _ReadLoose1(self, path, name):
     try:
-      fd = open(path)
-    except IOError:
-      return
-
-    try:
-      try:
+      with open(path) as fd:
         mtime = os.path.getmtime(path)
         ref_id = fd.readline()
-      except (IOError, OSError):
-        return
-    finally:
-      fd.close()
+    except (IOError, OSError):
+      return
 
     try:
       ref_id = ref_id.decode()
diff --git a/project.py b/project.py
index a2a3adc..6a48c23 100755
--- a/project.py
+++ b/project.py
@@ -58,11 +58,8 @@
 def _lwrite(path, content):
   lock = '%s.lock' % path
 
-  fd = open(lock, 'w')
-  try:
+  with open(lock, 'w') as fd:
     fd.write(content)
-  finally:
-    fd.close()
 
   try:
     platform_utils.rename(lock, path)
@@ -1393,12 +1390,9 @@
     if is_new:
       alt = os.path.join(self.gitdir, 'objects/info/alternates')
       try:
-        fd = open(alt)
-        try:
+        with open(alt) as fd:
           # This works for both absolute and relative alternate directories.
           alt_dir = os.path.join(self.objdir, 'objects', fd.readline().rstrip())
-        finally:
-          fd.close()
       except IOError:
         alt_dir = None
     else:
@@ -2893,14 +2887,11 @@
       else:
         path = os.path.join(self._project.worktree, '.git', HEAD)
       try:
-        fd = open(path)
+        with open(path) as fd:
+          line = fd.readline()
       except IOError as e:
         raise NoManifestException(path, str(e))
       try:
-        line = fd.readline()
-      finally:
-        fd.close()
-      try:
         line = line.decode()
       except AttributeError:
         pass
diff --git a/repo b/repo
index 2f634d9..90cdb60 100755
--- a/repo
+++ b/repo
@@ -513,9 +513,8 @@
     sys.exit(1)
   print()
 
-  fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
-  fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
-  fd.close()
+  with open(os.path.join(home_dot_repo, 'keyring-version'), 'w') as fd:
+    fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
   return True
 
 
diff --git a/subcmds/manifest.py b/subcmds/manifest.py
index 768f072..9c1b3f0 100644
--- a/subcmds/manifest.py
+++ b/subcmds/manifest.py
@@ -40,10 +40,9 @@
     helptext = self._helpDescription + '\n'
     r = os.path.dirname(__file__)
     r = os.path.dirname(r)
-    fd = open(os.path.join(r, 'docs', 'manifest-format.md'))
-    for line in fd:
-      helptext += line
-    fd.close()
+    with open(os.path.join(r, 'docs', 'manifest-format.md')) as fd:
+      for line in fd:
+        helptext += line
     return helptext
 
   def _Options(self, p):
diff --git a/subcmds/sync.py b/subcmds/sync.py
index f77a785..9b4a614 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -692,11 +692,8 @@
     old_project_paths = []
 
     if os.path.exists(file_path):
-      fd = open(file_path, 'r')
-      try:
+      with open(file_path, 'r') as fd:
         old_project_paths = fd.read().split('\n')
-      finally:
-        fd.close()
       # In reversed order, so subfolders are deleted before parent folder.
       for path in sorted(old_project_paths, reverse=True):
         if not path:
@@ -731,12 +728,9 @@
               return 1
 
     new_project_paths.sort()
-    fd = open(file_path, 'w')
-    try:
+    with open(file_path, 'w') as fd:
       fd.write('\n'.join(new_project_paths))
       fd.write('\n')
-    finally:
-      fd.close()
     return 0
 
   def _SmartSyncSetup(self, opt, smart_sync_manifest_path):
@@ -809,11 +803,8 @@
       if success:
         manifest_name = os.path.basename(smart_sync_manifest_path)
         try:
-          f = open(smart_sync_manifest_path, 'w')
-          try:
+          with open(smart_sync_manifest_path, 'w') as f:
             f.write(manifest_str)
-          finally:
-            f.close()
         except IOError as e:
           print('error: cannot write manifest to %s:\n%s'
                 % (smart_sync_manifest_path, e),
@@ -1102,11 +1093,8 @@
   def _Load(self):
     if self._times is None:
       try:
-        f = open(self._path)
-        try:
+        with open(self._path) as f:
           self._times = json.load(f)
-        finally:
-          f.close()
       except (IOError, ValueError):
         try:
           platform_utils.remove(self._path)
@@ -1126,11 +1114,8 @@
       del self._times[name]
 
     try:
-      f = open(self._path, 'w')
-      try:
+      with open(self._path, 'w') as f:
         json.dump(self._times, f, indent=2)
-      finally:
-        f.close()
     except (IOError, TypeError):
       try:
         platform_utils.remove(self._path)