コード例 #1
0
ファイル: git_config.py プロジェクト: I2SE/git-repo
 def _SaveJson(self, cache):
     try:
         with open(self._json, 'w') as fd:
             json.dump(cache, fd, indent=2)
     except (IOError, TypeError):
         if os.path.exists(self._json):
             platform_utils.remove(self._json)
コード例 #2
0
    def Link(self, name):
        """Update the repo metadata to use a different manifest.
    """
        self.Override(name)

        # Old versions of repo would generate symlinks we need to clean up.
        if os.path.lexists(self.manifestFile):
            platform_utils.remove(self.manifestFile)
        # This file is interpreted as if it existed inside the manifest repo.
        # That allows us to use <include> with the relative file name.
        with open(self.manifestFile, 'w') as fp:
            fp.write("""<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT THIS FILE!  It is generated by repo and changes will be discarded.
If you want to use a different manifest, use `repo init -m <file>` instead.

If you want to customize your checkout by overriding manifest settings, use
the local_manifests/ directory instead.

For more information on repo manifests, check out:
https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
-->
<manifest>
  <include name="%s" />
</manifest>
""" % (name, ))
コード例 #3
0
 def _Load(self):
   if self._times is None:
     try:
       with open(self._path) as f:
         self._times = json.load(f)
     except (IOError, ValueError):
       platform_utils.remove(self._path, missing_ok=True)
       self._times = {}
コード例 #4
0
  def _DeleteProject(self, path):
    print('Deleting obsolete path %s' % path, file=sys.stderr)

    # Delete the .git directory first, so we're less likely to have a partially
    # working git repository around. There shouldn't be any git projects here,
    # so rmtree works.
    try:
      platform_utils.rmtree(os.path.join(path, '.git'))
    except OSError:
      print('Failed to remove %s' % os.path.join(path, '.git'), file=sys.stderr)
      print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
      print('       remove manually, then run sync again', file=sys.stderr)
      return -1

    # Delete everything under the worktree, except for directories that contain
    # another git project
    dirs_to_remove = []
    failed = False
    for root, dirs, files in os.walk(path):
      for f in files:
        try:
          platform_utils.remove(os.path.join(root, f))
        except OSError:
          print('Failed to remove %s' % os.path.join(root, f), file=sys.stderr)
          failed = True
      dirs[:] = [d for d in dirs
                 if not os.path.lexists(os.path.join(root, d, '.git'))]
      dirs_to_remove += [os.path.join(root, d) for d in dirs
                         if os.path.join(root, d) not in dirs_to_remove]
    for d in reversed(dirs_to_remove):
      if platform_utils.islink(d):
        try:
          platform_utils.remove(d)
        except OSError:
          print('Failed to remove %s' % os.path.join(root, d), file=sys.stderr)
          failed = True
      elif len(os.listdir(d)) == 0:
        try:
          os.rmdir(d)
        except OSError:
          print('Failed to remove %s' % os.path.join(root, d), file=sys.stderr)
          failed = True
          continue
    if failed:
      print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
      print('       remove manually, then run sync again', file=sys.stderr)
      return -1

    # Try deleting parent dirs if they are empty
    project_dir = path
    while project_dir != self.manifest.topdir:
      if len(os.listdir(project_dir)) == 0:
        os.rmdir(project_dir)
      else:
        break
      project_dir = os.path.dirname(project_dir)

    return 0
コード例 #5
0
ファイル: sync.py プロジェクト: derek1010/git-repo2
  def _DeleteProject(self, path):
    print('Deleting obsolete path %s' % path, file=sys.stderr)

    # Delete the .git directory first, so we're less likely to have a partially
    # working git repository around. There shouldn't be any git projects here,
    # so rmtree works.
    try:
      platform_utils.rmtree(os.path.join(path, '.git'))
    except OSError:
      print('Failed to remove %s' % os.path.join(path, '.git'), file=sys.stderr)
      print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
      print('       remove manually, then run sync again', file=sys.stderr)
      return -1

    # Delete everything under the worktree, except for directories that contain
    # another git project
    dirs_to_remove = []
    failed = False
    for root, dirs, files in os.walk(path):
      for f in files:
        try:
          platform_utils.remove(os.path.join(root, f))
        except OSError:
          print('Failed to remove %s' % os.path.join(root, f), file=sys.stderr)
          failed = True
      dirs[:] = [d for d in dirs
                 if not os.path.lexists(os.path.join(root, d, '.git'))]
      dirs_to_remove += [os.path.join(root, d) for d in dirs
                         if os.path.join(root, d) not in dirs_to_remove]
    for d in reversed(dirs_to_remove):
      if platform_utils.islink(d):
        try:
          platform_utils.remove(d)
        except OSError:
          print('Failed to remove %s' % os.path.join(root, d), file=sys.stderr)
          failed = True
      elif len(os.listdir(d)) == 0:
        try:
          os.rmdir(d)
        except OSError:
          print('Failed to remove %s' % os.path.join(root, d), file=sys.stderr)
          failed = True
          continue
    if failed:
      print('error: Failed to delete obsolete path %s' % path, file=sys.stderr)
      print('       remove manually, then run sync again', file=sys.stderr)
      return -1

    # Try deleting parent dirs if they are empty
    project_dir = path
    while project_dir != self.manifest.topdir:
      if len(os.listdir(project_dir)) == 0:
        os.rmdir(project_dir)
      else:
        break
      project_dir = os.path.dirname(project_dir)

    return 0
コード例 #6
0
 def _SaveJson(self, cache):
     try:
         fd = open(self._json, 'w')
         try:
             json.dump(cache, fd, indent=2)
         finally:
             fd.close()
     except (IOError, TypeError):
         if os.path.exists(self._json):
             platform_utils.remove(self._json)
コード例 #7
0
ファイル: git_config.py プロジェクト: derek1010/git-repo2
 def _SaveJson(self, cache):
   try:
     fd = open(self._json, 'w')
     try:
       json.dump(cache, fd, indent=2)
     finally:
       fd.close()
   except (IOError, TypeError):
     if os.path.exists(self._json):
       platform_utils.remove(self._json)
コード例 #8
0
 def _Load(self):
     if self._times is None:
         try:
             with open(self._path) as f:
                 self._times = json.load(f)
         except (IOError, ValueError):
             try:
                 platform_utils.remove(self._path)
             except OSError:
                 pass
             self._times = {}
コード例 #9
0
  def Link(self, name):
    """Update the repo metadata to use a different manifest.
    """
    self.Override(name)

    try:
      if os.path.lexists(self.manifestFile):
        platform_utils.remove(self.manifestFile)
      platform_utils.symlink(os.path.join('manifests', name), self.manifestFile)
    except OSError as e:
      raise ManifestParseError('cannot link manifest %s: %s' % (name, str(e)))
コード例 #10
0
ファイル: manifest_xml.py プロジェクト: android/tools_repo
  def Link(self, name):
    """Update the repo metadata to use a different manifest.
    """
    self.Override(name)

    try:
      if os.path.lexists(self.manifestFile):
        platform_utils.remove(self.manifestFile)
      platform_utils.symlink(os.path.join('manifests', name), self.manifestFile)
    except OSError as e:
      raise ManifestParseError('cannot link manifest %s: %s' % (name, str(e)))
コード例 #11
0
    def EditString(cls, data):
        """Opens an editor to edit the given content.

    Args:
      data: The text to edit.

    Returns:
      New value of edited text.

    Raises:
      EditorError: The editor failed to run.
    """
        editor = cls._GetEditor()
        if editor == ":":
            return data

        fd, path = tempfile.mkstemp()
        try:
            os.write(fd, data.encode("utf-8"))
            os.close(fd)
            fd = None

            if platform_utils.isWindows():
                # Split on spaces, respecting quoted strings
                import shlex

                args = shlex.split(editor)
                shell = False
            elif re.compile("^.*[$ \t'].*$").match(editor):
                args = [editor + ' "$@"', "sh"]
                shell = True
            else:
                args = [editor]
                shell = False
            args.append(path)

            try:
                rc = subprocess.Popen(args, shell=shell).wait()
            except OSError as e:
                raise EditorError("editor failed, %s: %s %s" %
                                  (str(e), editor, path))
            if rc != 0:
                raise EditorError("editor failed with exit status %d: %s %s" %
                                  (rc, editor, path))

            with open(path, mode="rb") as fd2:
                return fd2.read().decode("utf-8")
        finally:
            if fd:
                os.close(fd)
            platform_utils.remove(path)
コード例 #12
0
ファイル: editor.py プロジェクト: android/tools_repo
  def EditString(cls, data):
    """Opens an editor to edit the given content.

       Args:
         data        : the text to edit

      Returns:
        new value of edited text; None if editing did not succeed
    """
    editor = cls._GetEditor()
    if editor == ':':
      return data

    fd, path = tempfile.mkstemp()
    try:
      os.write(fd, data)
      os.close(fd)
      fd = None

      if platform_utils.isWindows():
        # Split on spaces, respecting quoted strings
        import shlex
        args = shlex.split(editor)
        shell = False
      elif re.compile("^.*[$ \t'].*$").match(editor):
        args = [editor + ' "$@"', 'sh']
        shell = True
      else:
        args = [editor]
        shell = False
      args.append(path)

      try:
        rc = subprocess.Popen(args, shell=shell).wait()
      except OSError as e:
        raise EditorError('editor failed, %s: %s %s'
          % (str(e), editor, path))
      if rc != 0:
        raise EditorError('editor failed with exit status %d: %s %s'
          % (rc, editor, path))

      fd2 = open(path)
      try:
        return fd2.read()
      finally:
        fd2.close()
    finally:
      if fd:
        os.close(fd)
      platform_utils.remove(path)
コード例 #13
0
ファイル: git_config.py プロジェクト: I2SE/git-repo
 def _ReadJson(self):
     try:
         if os.path.getmtime(self._json) <= os.path.getmtime(self.file):
             platform_utils.remove(self._json)
             return None
     except OSError:
         return None
     try:
         Trace(': parsing %s', self.file)
         with open(self._json) as fd:
             return json.load(fd)
     except (IOError, ValueError):
         platform_utils.remove(self._json)
         return None
コード例 #14
0
ファイル: sync.py プロジェクト: derek1010/git-repo2
 def _Load(self):
   if self._times is None:
     try:
       f = open(self._path)
       try:
         self._times = json.load(f)
       finally:
         f.close()
     except (IOError, ValueError):
       try:
         platform_utils.remove(self._path)
       except OSError:
         pass
       self._times = {}
コード例 #15
0
ファイル: editor.py プロジェクト: derek1010/git-repo2
    def EditString(cls, data):
        """Opens an editor to edit the given content.

       Args:
         data        : the text to edit

      Returns:
        new value of edited text; None if editing did not succeed
    """
        editor = cls._GetEditor()
        if editor == ':':
            return data

        fd, path = tempfile.mkstemp()
        try:
            os.write(fd, data)
            os.close(fd)
            fd = None

            if platform_utils.isWindows():
                # Split on spaces, respecting quoted strings
                import shlex
                args = shlex.split(editor)
                shell = False
            elif re.compile("^.*[$ \t'].*$").match(editor):
                args = [editor + ' "$@"', 'sh']
                shell = True
            else:
                args = [editor]
                shell = False
            args.append(path)

            try:
                rc = subprocess.Popen(args, shell=shell).wait()
            except OSError as e:
                raise EditorError('editor failed, %s: %s %s' %
                                  (str(e), editor, path))
            if rc != 0:
                raise EditorError('editor failed with exit status %d: %s %s' %
                                  (rc, editor, path))

            fd2 = open(path)
            try:
                return fd2.read()
            finally:
                fd2.close()
        finally:
            if fd:
                os.close(fd)
            platform_utils.remove(path)
コード例 #16
0
 def _Load(self):
   if self._times is None:
     try:
       f = open(self._path)
       try:
         self._times = json.load(f)
       finally:
         f.close()
     except (IOError, ValueError):
       try:
         platform_utils.remove(self._path)
       except OSError:
         pass
       self._times = {}
コード例 #17
0
    def testMissingOk(self):
        """Check missing_ok handling."""
        with tempfile.TemporaryDirectory() as tmpdir:
            path = os.path.join(tmpdir, 'test')

            # Should not fail.
            platform_utils.remove(path, missing_ok=True)

            # Should fail.
            self.assertRaises(OSError, platform_utils.remove, path)
            self.assertRaises(OSError,
                              platform_utils.remove,
                              path,
                              missing_ok=False)

            # Should not fail if it exists.
            open(path, 'w').close()
            platform_utils.remove(path, missing_ok=True)
            self.assertFalse(os.path.exists(path))

            open(path, 'w').close()
            platform_utils.remove(path)
            self.assertFalse(os.path.exists(path))

            open(path, 'w').close()
            platform_utils.remove(path, missing_ok=False)
            self.assertFalse(os.path.exists(path))
コード例 #18
0
  def UpdateCopyLinkfileList(self):
    """Save all dests of copyfile and linkfile, and update them if needed.

    Returns:
      Whether update was successful.
    """
    new_paths = {}
    new_linkfile_paths = []
    new_copyfile_paths = []
    for project in self.GetProjects(None, missing_ok=True):
      new_linkfile_paths.extend(x.dest for x in project.linkfiles)
      new_copyfile_paths.extend(x.dest for x in project.copyfiles)

    new_paths = {
        'linkfile': new_linkfile_paths,
        'copyfile': new_copyfile_paths,
    }

    copylinkfile_name = 'copy-link-files.json'
    copylinkfile_path = os.path.join(self.manifest.repodir, copylinkfile_name)
    old_copylinkfile_paths = {}

    if os.path.exists(copylinkfile_path):
      with open(copylinkfile_path, 'rb') as fp:
        try:
          old_copylinkfile_paths = json.load(fp)
        except Exception:
          print('error: %s is not a json formatted file.' %
                copylinkfile_path, file=sys.stderr)
          platform_utils.remove(copylinkfile_path)
          return False

      need_remove_files = []
      need_remove_files.extend(
          set(old_copylinkfile_paths.get('linkfile', [])) -
          set(new_linkfile_paths))
      need_remove_files.extend(
          set(old_copylinkfile_paths.get('copyfile', [])) -
          set(new_copyfile_paths))

      for need_remove_file in need_remove_files:
        # Try to remove the updated copyfile or linkfile.
        # So, if the file is not exist, nothing need to do.
        platform_utils.remove(need_remove_file, missing_ok=True)

    # Create copy-link-files.json, save dest path of "copyfile" and "linkfile".
    with open(copylinkfile_path, 'w', encoding='utf-8') as fp:
      json.dump(new_paths, fp)
    return True
コード例 #19
0
  def Save(self):
    if self._times is None:
      return

    to_delete = []
    for name in self._times:
      if name not in self._seen:
        to_delete.append(name)
    for name in to_delete:
      del self._times[name]

    try:
      with open(self._path, 'w') as f:
        json.dump(self._times, f, indent=2)
    except (IOError, TypeError):
      platform_utils.remove(self._path, missing_ok=True)
コード例 #20
0
ファイル: git_config.py プロジェクト: derek1010/git-repo2
 def _ReadJson(self):
   try:
     if os.path.getmtime(self._json) \
     <= os.path.getmtime(self.file):
       platform_utils.remove(self._json)
       return None
   except OSError:
     return None
   try:
     Trace(': parsing %s', self.file)
     fd = open(self._json)
     try:
       return json.load(fd)
     finally:
       fd.close()
   except (IOError, ValueError):
     platform_utils.remove(self._json)
     return None
コード例 #21
0
 def _ReadJson(self):
     try:
         if os.path.getmtime(self._json) \
         <= os.path.getmtime(self.file):
             platform_utils.remove(self._json)
             return None
     except OSError:
         return None
     try:
         Trace(': parsing %s', self.file)
         fd = open(self._json)
         try:
             return json.load(fd)
         finally:
             fd.close()
     except (IOError, ValueError):
         platform_utils.remove(self._json)
         return None
コード例 #22
0
ファイル: sync.py プロジェクト: derek1010/git-repo2
  def Save(self):
    if self._times is None:
      return

    to_delete = []
    for name in self._times:
      if name not in self._seen:
        to_delete.append(name)
    for name in to_delete:
      del self._times[name]

    try:
      f = open(self._path, 'w')
      try:
        json.dump(self._times, f, indent=2)
      finally:
        f.close()
    except (IOError, TypeError):
      try:
        platform_utils.remove(self._path)
      except OSError:
        pass
コード例 #23
0
  def Save(self):
    if self._times is None:
      return

    to_delete = []
    for name in self._times:
      if name not in self._seen:
        to_delete.append(name)
    for name in to_delete:
      del self._times[name]

    try:
      f = open(self._path, 'w')
      try:
        json.dump(self._times, f, indent=2)
      finally:
        f.close()
    except (IOError, TypeError):
      try:
        platform_utils.remove(self._path)
      except OSError:
        pass
コード例 #24
0
  def Execute(self, opt, args):
    if opt.jobs:
      self.jobs = opt.jobs
    if self.jobs > 1:
      soft_limit, _ = _rlimit_nofile()
      self.jobs = min(self.jobs, (soft_limit - 5) / 3)

    if opt.network_only and opt.detach_head:
      print('error: cannot combine -n and -d', file=sys.stderr)
      sys.exit(1)
    if opt.network_only and opt.local_only:
      print('error: cannot combine -n and -l', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_name and opt.smart_sync:
      print('error: cannot combine -m and -s', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_name and opt.smart_tag:
      print('error: cannot combine -m and -t', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_server_username or opt.manifest_server_password:
      if not (opt.smart_sync or opt.smart_tag):
        print('error: -u and -p may only be combined with -s or -t',
              file=sys.stderr)
        sys.exit(1)
      if None in [opt.manifest_server_username, opt.manifest_server_password]:
        print('error: both -u and -p must be given', file=sys.stderr)
        sys.exit(1)

    if opt.manifest_name:
      self.manifest.Override(opt.manifest_name)

    manifest_name = opt.manifest_name
    smart_sync_manifest_name = "smart_sync_override.xml"
    smart_sync_manifest_path = os.path.join(
      self.manifest.manifestProject.worktree, smart_sync_manifest_name)

    if opt.smart_sync or opt.smart_tag:
      if not self.manifest.manifest_server:
        print('error: cannot smart sync: no manifest server defined in '
              'manifest', file=sys.stderr)
        sys.exit(1)

      manifest_server = self.manifest.manifest_server
      if not opt.quiet:
        print('Using manifest server %s' % manifest_server)

      if not '@' in manifest_server:
        username = None
        password = None
        if opt.manifest_server_username and opt.manifest_server_password:
          username = opt.manifest_server_username
          password = opt.manifest_server_password
        else:
          try:
            info = netrc.netrc()
          except IOError:
            # .netrc file does not exist or could not be opened
            pass
          else:
            try:
              parse_result = urllib.parse.urlparse(manifest_server)
              if parse_result.hostname:
                auth = info.authenticators(parse_result.hostname)
                if auth:
                  username, _account, password = auth
                else:
                  print('No credentials found for %s in .netrc'
                        % parse_result.hostname, file=sys.stderr)
            except netrc.NetrcParseError as e:
              print('Error parsing .netrc file: %s' % e, file=sys.stderr)

        if (username and password):
          manifest_server = manifest_server.replace('://', '://%s:%s@' %
                                                    (username, password),
                                                    1)

      transport = PersistentTransport(manifest_server)
      if manifest_server.startswith('persistent-'):
        manifest_server = manifest_server[len('persistent-'):]

      try:
        server = xmlrpc.client.Server(manifest_server, transport=transport)
        if opt.smart_sync:
          p = self.manifest.manifestProject
          b = p.GetBranch(p.CurrentBranch)
          branch = b.merge
          if branch.startswith(R_HEADS):
            branch = branch[len(R_HEADS):]

          env = os.environ.copy()
          if 'SYNC_TARGET' in env:
            target = env['SYNC_TARGET']
            [success, manifest_str] = server.GetApprovedManifest(branch, target)
          elif 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env:
            target = '%s-%s' % (env['TARGET_PRODUCT'],
                                env['TARGET_BUILD_VARIANT'])
            [success, manifest_str] = server.GetApprovedManifest(branch, target)
          else:
            [success, manifest_str] = server.GetApprovedManifest(branch)
        else:
          assert(opt.smart_tag)
          [success, manifest_str] = server.GetManifest(opt.smart_tag)

        if success:
          manifest_name = smart_sync_manifest_name
          try:
            f = open(smart_sync_manifest_path, 'w')
            try:
              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),
                  file=sys.stderr)
            sys.exit(1)
          self._ReloadManifest(manifest_name)
        else:
          print('error: manifest server RPC call failed: %s' %
                manifest_str, file=sys.stderr)
          sys.exit(1)
      except (socket.error, IOError, xmlrpc.client.Fault) as e:
        print('error: cannot connect to manifest server %s:\n%s'
              % (self.manifest.manifest_server, e), file=sys.stderr)
        sys.exit(1)
      except xmlrpc.client.ProtocolError as e:
        print('error: cannot connect to manifest server %s:\n%d %s'
              % (self.manifest.manifest_server, e.errcode, e.errmsg),
              file=sys.stderr)
        sys.exit(1)
    else:  # Not smart sync or smart tag mode
      if os.path.isfile(smart_sync_manifest_path):
        try:
          platform_utils.remove(smart_sync_manifest_path)
        except OSError as e:
          print('error: failed to remove existing smart sync override manifest: %s' %
                e, file=sys.stderr)

    rp = self.manifest.repoProject
    rp.PreSync()

    mp = self.manifest.manifestProject
    mp.PreSync()

    if opt.repo_upgraded:
      _PostRepoUpgrade(self.manifest, quiet=opt.quiet)

    if not opt.local_only:
      start = time.time()
      success = mp.Sync_NetworkHalf(quiet=opt.quiet,
                                    current_branch_only=opt.current_branch_only,
                                    no_tags=opt.no_tags,
                                    optimized_fetch=opt.optimized_fetch,
                                    submodules=self.manifest.HasSubmodules)
      finish = time.time()
      self.event_log.AddSync(mp, event_log.TASK_SYNC_NETWORK,
                             start, finish, success)

    if mp.HasChanges:
      syncbuf = SyncBuffer(mp.config)
      start = time.time()
      mp.Sync_LocalHalf(syncbuf, submodules=self.manifest.HasSubmodules)
      clean = syncbuf.Finish()
      self.event_log.AddSync(mp, event_log.TASK_SYNC_LOCAL,
                             start, time.time(), clean)
      if not clean:
        sys.exit(1)
      self._ReloadManifest(manifest_name)
      if opt.jobs is None:
        self.jobs = self.manifest.default.sync_j

    if self.gitc_manifest:
      gitc_manifest_projects = self.GetProjects(args,
                                                missing_ok=True)
      gitc_projects = []
      opened_projects = []
      for project in gitc_manifest_projects:
        if project.relpath in self.gitc_manifest.paths and \
           self.gitc_manifest.paths[project.relpath].old_revision:
          opened_projects.append(project.relpath)
        else:
          gitc_projects.append(project.relpath)

      if not args:
        gitc_projects = None

      if gitc_projects != [] and not opt.local_only:
        print('Updating GITC client: %s' % self.gitc_manifest.gitc_client_name)
        manifest = GitcManifest(self.repodir, self.gitc_manifest.gitc_client_name)
        if manifest_name:
          manifest.Override(manifest_name)
        else:
          manifest.Override(self.manifest.manifestFile)
        gitc_utils.generate_gitc_manifest(self.gitc_manifest,
                                          manifest,
                                          gitc_projects)
        print('GITC client successfully synced.')

      # The opened projects need to be synced as normal, therefore we
      # generate a new args list to represent the opened projects.
      # TODO: make this more reliable -- if there's a project name/path overlap,
      # this may choose the wrong project.
      args = [os.path.relpath(self.manifest.paths[path].worktree, os.getcwd())
              for path in opened_projects]
      if not args:
        return
    all_projects = self.GetProjects(args,
                                    missing_ok=True,
                                    submodules_ok=opt.fetch_submodules)

    self._fetch_times = _FetchTimes(self.manifest)
    if not opt.local_only:
      to_fetch = []
      now = time.time()
      if _ONE_DAY_S <= (now - rp.LastFetch):
        to_fetch.append(rp)
      to_fetch.extend(all_projects)
      to_fetch.sort(key=self._fetch_times.Get, reverse=True)

      fetched = self._Fetch(to_fetch, opt)
      _PostRepoFetch(rp, opt.no_repo_verify)
      if opt.network_only:
        # bail out now; the rest touches the working tree
        return

      # Iteratively fetch missing and/or nested unregistered submodules
      previously_missing_set = set()
      while True:
        self._ReloadManifest(manifest_name)
        all_projects = self.GetProjects(args,
                                        missing_ok=True,
                                        submodules_ok=opt.fetch_submodules)
        missing = []
        for project in all_projects:
          if project.gitdir not in fetched:
            missing.append(project)
        if not missing:
          break
        # Stop us from non-stopped fetching actually-missing repos: If set of
        # missing repos has not been changed from last fetch, we break.
        missing_set = set(p.name for p in missing)
        if previously_missing_set == missing_set:
          break
        previously_missing_set = missing_set
        fetched.update(self._Fetch(missing, opt))

    if self.manifest.IsMirror or self.manifest.IsArchive:
      # bail out now, we have no working tree
      return

    if self.UpdateProjectList():
      sys.exit(1)

    syncbuf = SyncBuffer(mp.config,
                         detach_head = opt.detach_head)
    pm = Progress('Syncing work tree', len(all_projects))
    for project in all_projects:
      pm.update()
      if project.worktree:
        start = time.time()
        project.Sync_LocalHalf(syncbuf, force_sync=opt.force_sync)
        self.event_log.AddSync(project, event_log.TASK_SYNC_LOCAL,
                               start, time.time(), syncbuf.Recently())
    pm.end()
    print(file=sys.stderr)
    if not syncbuf.Finish():
      sys.exit(1)

    # If there's a notice that's supposed to print at the end of the sync, print
    # it now...
    if self.manifest.notice:
      print(self.manifest.notice)
コード例 #25
0
ファイル: sync.py プロジェクト: trbmsdb/git-repo
    def Execute(self, opt, args):
        if opt.jobs:
            self.jobs = opt.jobs
        if self.jobs > 1:
            soft_limit, _ = _rlimit_nofile()
            self.jobs = min(self.jobs, (soft_limit - 5) // 3)

        if opt.manifest_name:
            self.manifest.Override(opt.manifest_name)

        manifest_name = opt.manifest_name
        smart_sync_manifest_path = os.path.join(
            self.manifest.manifestProject.worktree, 'smart_sync_override.xml')

        if opt.smart_sync or opt.smart_tag:
            manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path)
        else:
            if os.path.isfile(smart_sync_manifest_path):
                try:
                    platform_utils.remove(smart_sync_manifest_path)
                except OSError as e:
                    print(
                        'error: failed to remove existing smart sync override manifest: %s'
                        % e,
                        file=sys.stderr)

        rp = self.manifest.repoProject
        rp.PreSync()

        mp = self.manifest.manifestProject
        mp.PreSync()

        if opt.repo_upgraded:
            _PostRepoUpgrade(self.manifest, quiet=opt.quiet)

        self._UpdateManifestProject(opt, mp, manifest_name)

        if self.gitc_manifest:
            gitc_manifest_projects = self.GetProjects(args, missing_ok=True)
            gitc_projects = []
            opened_projects = []
            for project in gitc_manifest_projects:
                if project.relpath in self.gitc_manifest.paths and \
                   self.gitc_manifest.paths[project.relpath].old_revision:
                    opened_projects.append(project.relpath)
                else:
                    gitc_projects.append(project.relpath)

            if not args:
                gitc_projects = None

            if gitc_projects != [] and not opt.local_only:
                print('Updating GITC client: %s' %
                      self.gitc_manifest.gitc_client_name)
                manifest = GitcManifest(self.repodir,
                                        self.gitc_manifest.gitc_client_name)
                if manifest_name:
                    manifest.Override(manifest_name)
                else:
                    manifest.Override(self.manifest.manifestFile)
                gitc_utils.generate_gitc_manifest(self.gitc_manifest, manifest,
                                                  gitc_projects)
                print('GITC client successfully synced.')

            # The opened projects need to be synced as normal, therefore we
            # generate a new args list to represent the opened projects.
            # TODO: make this more reliable -- if there's a project name/path overlap,
            # this may choose the wrong project.
            args = [
                os.path.relpath(self.manifest.paths[path].worktree,
                                os.getcwd()) for path in opened_projects
            ]
            if not args:
                return
        all_projects = self.GetProjects(args,
                                        missing_ok=True,
                                        submodules_ok=opt.fetch_submodules)

        self._fetch_times = _FetchTimes(self.manifest)
        if not opt.local_only:
            to_fetch = []
            now = time.time()
            if _ONE_DAY_S <= (now - rp.LastFetch):
                to_fetch.append(rp)
            to_fetch.extend(all_projects)
            to_fetch.sort(key=self._fetch_times.Get, reverse=True)

            fetched = self._Fetch(to_fetch, opt)
            _PostRepoFetch(rp, opt.no_repo_verify)
            if opt.network_only:
                # bail out now; the rest touches the working tree
                return

            # Iteratively fetch missing and/or nested unregistered submodules
            previously_missing_set = set()
            while True:
                self._ReloadManifest(manifest_name)
                all_projects = self.GetProjects(
                    args, missing_ok=True, submodules_ok=opt.fetch_submodules)
                missing = []
                for project in all_projects:
                    if project.gitdir not in fetched:
                        missing.append(project)
                if not missing:
                    break
                # Stop us from non-stopped fetching actually-missing repos: If set of
                # missing repos has not been changed from last fetch, we break.
                missing_set = set(p.name for p in missing)
                if previously_missing_set == missing_set:
                    break
                previously_missing_set = missing_set
                fetched.update(self._Fetch(missing, opt))

        if self.manifest.IsMirror or self.manifest.IsArchive:
            # bail out now, we have no working tree
            return

        if self.UpdateProjectList(opt):
            sys.exit(1)

        self._Checkout(all_projects, opt)

        # If there's a notice that's supposed to print at the end of the sync, print
        # it now...
        if self.manifest.notice:
            print(self.manifest.notice)
コード例 #26
0
ファイル: sync.py プロジェクト: derek1010/git-repo2
  def Execute(self, opt, args):
    if opt.jobs:
      self.jobs = opt.jobs
    if self.jobs > 1:
      soft_limit, _ = _rlimit_nofile()
      self.jobs = min(self.jobs, (soft_limit - 5) / 3)

    if opt.network_only and opt.detach_head:
      print('error: cannot combine -n and -d', file=sys.stderr)
      sys.exit(1)
    if opt.network_only and opt.local_only:
      print('error: cannot combine -n and -l', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_name and opt.smart_sync:
      print('error: cannot combine -m and -s', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_name and opt.smart_tag:
      print('error: cannot combine -m and -t', file=sys.stderr)
      sys.exit(1)
    if opt.manifest_server_username or opt.manifest_server_password:
      if not (opt.smart_sync or opt.smart_tag):
        print('error: -u and -p may only be combined with -s or -t',
              file=sys.stderr)
        sys.exit(1)
      if None in [opt.manifest_server_username, opt.manifest_server_password]:
        print('error: both -u and -p must be given', file=sys.stderr)
        sys.exit(1)

    if opt.manifest_name:
      self.manifest.Override(opt.manifest_name)

    manifest_name = opt.manifest_name
    smart_sync_manifest_name = "smart_sync_override.xml"
    smart_sync_manifest_path = os.path.join(
      self.manifest.manifestProject.worktree, smart_sync_manifest_name)

    if opt.smart_sync or opt.smart_tag:
      if not self.manifest.manifest_server:
        print('error: cannot smart sync: no manifest server defined in '
              'manifest', file=sys.stderr)
        sys.exit(1)

      manifest_server = self.manifest.manifest_server
      if not opt.quiet:
        print('Using manifest server %s' % manifest_server)

      if not '@' in manifest_server:
        username = None
        password = None
        if opt.manifest_server_username and opt.manifest_server_password:
          username = opt.manifest_server_username
          password = opt.manifest_server_password
        else:
          try:
            info = netrc.netrc()
          except IOError:
            # .netrc file does not exist or could not be opened
            pass
          else:
            try:
              parse_result = urllib.parse.urlparse(manifest_server)
              if parse_result.hostname:
                auth = info.authenticators(parse_result.hostname)
                if auth:
                  username, _account, password = auth
                else:
                  print('No credentials found for %s in .netrc'
                        % parse_result.hostname, file=sys.stderr)
            except netrc.NetrcParseError as e:
              print('Error parsing .netrc file: %s' % e, file=sys.stderr)

        if (username and password):
          manifest_server = manifest_server.replace('://', '://%s:%s@' %
                                                    (username, password),
                                                    1)

      transport = PersistentTransport(manifest_server)
      if manifest_server.startswith('persistent-'):
        manifest_server = manifest_server[len('persistent-'):]

      try:
        server = xmlrpc.client.Server(manifest_server, transport=transport)
        if opt.smart_sync:
          p = self.manifest.manifestProject
          b = p.GetBranch(p.CurrentBranch)
          branch = b.merge
          if branch.startswith(R_HEADS):
            branch = branch[len(R_HEADS):]

          env = os.environ.copy()
          if 'SYNC_TARGET' in env:
            target = env['SYNC_TARGET']
            [success, manifest_str] = server.GetApprovedManifest(branch, target)
          elif 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env:
            target = '%s-%s' % (env['TARGET_PRODUCT'],
                                env['TARGET_BUILD_VARIANT'])
            [success, manifest_str] = server.GetApprovedManifest(branch, target)
          else:
            [success, manifest_str] = server.GetApprovedManifest(branch)
        else:
          assert(opt.smart_tag)
          [success, manifest_str] = server.GetManifest(opt.smart_tag)

        if success:
          manifest_name = smart_sync_manifest_name
          try:
            f = open(smart_sync_manifest_path, 'w')
            try:
              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),
                  file=sys.stderr)
            sys.exit(1)
          self._ReloadManifest(manifest_name)
        else:
          print('error: manifest server RPC call failed: %s' %
                manifest_str, file=sys.stderr)
          sys.exit(1)
      except (socket.error, IOError, xmlrpc.client.Fault) as e:
        print('error: cannot connect to manifest server %s:\n%s'
              % (self.manifest.manifest_server, e), file=sys.stderr)
        sys.exit(1)
      except xmlrpc.client.ProtocolError as e:
        print('error: cannot connect to manifest server %s:\n%d %s'
              % (self.manifest.manifest_server, e.errcode, e.errmsg),
              file=sys.stderr)
        sys.exit(1)
    else:  # Not smart sync or smart tag mode
      if os.path.isfile(smart_sync_manifest_path):
        try:
          platform_utils.remove(smart_sync_manifest_path)
        except OSError as e:
          print('error: failed to remove existing smart sync override manifest: %s' %
                e, file=sys.stderr)

    rp = self.manifest.repoProject
    rp.PreSync()

    mp = self.manifest.manifestProject
    mp.PreSync()

    if opt.repo_upgraded:
      _PostRepoUpgrade(self.manifest, quiet=opt.quiet)

    if not opt.local_only:
      start = time.time()
      success = mp.Sync_NetworkHalf(quiet=opt.quiet,
                                    current_branch_only=opt.current_branch_only,
                                    no_tags=opt.no_tags,
                                    optimized_fetch=opt.optimized_fetch,
                                    submodules=self.manifest.HasSubmodules)
      finish = time.time()
      self.event_log.AddSync(mp, event_log.TASK_SYNC_NETWORK,
                             start, finish, success)

    if mp.HasChanges:
      syncbuf = SyncBuffer(mp.config)
      start = time.time()
      mp.Sync_LocalHalf(syncbuf, submodules=self.manifest.HasSubmodules)
      clean = syncbuf.Finish()
      self.event_log.AddSync(mp, event_log.TASK_SYNC_LOCAL,
                             start, time.time(), clean)
      if not clean:
        sys.exit(1)
      self._ReloadManifest(manifest_name)
      if opt.jobs is None:
        self.jobs = self.manifest.default.sync_j

    if self.gitc_manifest:
      gitc_manifest_projects = self.GetProjects(args,
                                                missing_ok=True)
      gitc_projects = []
      opened_projects = []
      for project in gitc_manifest_projects:
        if project.relpath in self.gitc_manifest.paths and \
           self.gitc_manifest.paths[project.relpath].old_revision:
          opened_projects.append(project.relpath)
        else:
          gitc_projects.append(project.relpath)

      if not args:
        gitc_projects = None

      if gitc_projects != [] and not opt.local_only:
        print('Updating GITC client: %s' % self.gitc_manifest.gitc_client_name)
        manifest = GitcManifest(self.repodir, self.gitc_manifest.gitc_client_name)
        if manifest_name:
          manifest.Override(manifest_name)
        else:
          manifest.Override(self.manifest.manifestFile)
        gitc_utils.generate_gitc_manifest(self.gitc_manifest,
                                          manifest,
                                          gitc_projects)
        print('GITC client successfully synced.')

      # The opened projects need to be synced as normal, therefore we
      # generate a new args list to represent the opened projects.
      # TODO: make this more reliable -- if there's a project name/path overlap,
      # this may choose the wrong project.
      args = [os.path.relpath(self.manifest.paths[path].worktree, os.getcwd())
              for path in opened_projects]
      if not args:
        return
    all_projects = self.GetProjects(args,
                                    missing_ok=True,
                                    submodules_ok=opt.fetch_submodules)

    self._fetch_times = _FetchTimes(self.manifest)
    if not opt.local_only:
      to_fetch = []
      now = time.time()
      if _ONE_DAY_S <= (now - rp.LastFetch):
        to_fetch.append(rp)
      to_fetch.extend(all_projects)
      to_fetch.sort(key=self._fetch_times.Get, reverse=True)

      fetched = self._Fetch(to_fetch, opt)
      _PostRepoFetch(rp, opt.no_repo_verify)
      if opt.network_only:
        # bail out now; the rest touches the working tree
        return

      # Iteratively fetch missing and/or nested unregistered submodules
      previously_missing_set = set()
      while True:
        self._ReloadManifest(manifest_name)
        all_projects = self.GetProjects(args,
                                        missing_ok=True,
                                        submodules_ok=opt.fetch_submodules)
        missing = []
        for project in all_projects:
          if project.gitdir not in fetched:
            missing.append(project)
        if not missing:
          break
        # Stop us from non-stopped fetching actually-missing repos: If set of
        # missing repos has not been changed from last fetch, we break.
        missing_set = set(p.name for p in missing)
        if previously_missing_set == missing_set:
          break
        previously_missing_set = missing_set
        fetched.update(self._Fetch(missing, opt))

    if self.manifest.IsMirror or self.manifest.IsArchive:
      # bail out now, we have no working tree
      return

    if self.UpdateProjectList():
      sys.exit(1)

    syncbuf = SyncBuffer(mp.config,
                         detach_head = opt.detach_head)
    pm = Progress('Syncing work tree', len(all_projects))
    for project in all_projects:
      pm.update()
      if project.worktree:
        start = time.time()
        project.Sync_LocalHalf(syncbuf, force_sync=opt.force_sync)
        self.event_log.AddSync(project, event_log.TASK_SYNC_LOCAL,
                               start, time.time(), syncbuf.Recently())
    pm.end()
    print(file=sys.stderr)
    if not syncbuf.Finish():
      sys.exit(1)

    # If there's a notice that's supposed to print at the end of the sync, print
    # it now...
    if self.manifest.notice:
      print(self.manifest.notice)
コード例 #27
0
    def Execute(self, opt, args):
        if opt.jobs:
            self.jobs = opt.jobs
        if self.jobs > 1:
            soft_limit, _ = _rlimit_nofile()
            self.jobs = min(self.jobs, (soft_limit - 5) // 3)

        opt.quiet = opt.output_mode is False
        opt.verbose = opt.output_mode is True

        if opt.manifest_name:
            self.manifest.Override(opt.manifest_name)

        manifest_name = opt.manifest_name
        smart_sync_manifest_path = os.path.join(
            self.manifest.manifestProject.worktree, 'smart_sync_override.xml')

        if opt.clone_bundle is None:
            opt.clone_bundle = self.manifest.CloneBundle

        if opt.smart_sync or opt.smart_tag:
            manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path)
        else:
            if os.path.isfile(smart_sync_manifest_path):
                try:
                    platform_utils.remove(smart_sync_manifest_path)
                except OSError as e:
                    print(
                        'error: failed to remove existing smart sync override manifest: %s'
                        % e,
                        file=sys.stderr)

        err_event = _threading.Event()

        rp = self.manifest.repoProject
        rp.PreSync()
        cb = rp.CurrentBranch
        if cb:
            base = rp.GetBranch(cb).merge
            if not base or not base.startswith('refs/heads/'):
                print(
                    'warning: repo is not tracking a remote branch, so it will not '
                    'receive updates; run `repo init --repo-rev=stable` to fix.',
                    file=sys.stderr)

        mp = self.manifest.manifestProject
        mp.PreSync()

        if opt.repo_upgraded:
            _PostRepoUpgrade(self.manifest, quiet=opt.quiet)

        if not opt.mp_update:
            print('Skipping update of local manifest project.')
        else:
            self._UpdateManifestProject(opt, mp, manifest_name)

        if self.gitc_manifest:
            gitc_manifest_projects = self.GetProjects(args, missing_ok=True)
            gitc_projects = []
            opened_projects = []
            for project in gitc_manifest_projects:
                if project.relpath in self.gitc_manifest.paths and \
                   self.gitc_manifest.paths[project.relpath].old_revision:
                    opened_projects.append(project.relpath)
                else:
                    gitc_projects.append(project.relpath)

            if not args:
                gitc_projects = None

            if gitc_projects != [] and not opt.local_only:
                print('Updating GITC client: %s' %
                      self.gitc_manifest.gitc_client_name)
                manifest = GitcManifest(self.repodir,
                                        self.gitc_manifest.gitc_client_name)
                if manifest_name:
                    manifest.Override(manifest_name)
                else:
                    manifest.Override(self.manifest.manifestFile)
                gitc_utils.generate_gitc_manifest(self.gitc_manifest, manifest,
                                                  gitc_projects)
                print('GITC client successfully synced.')

            # The opened projects need to be synced as normal, therefore we
            # generate a new args list to represent the opened projects.
            # TODO: make this more reliable -- if there's a project name/path overlap,
            # this may choose the wrong project.
            args = [
                os.path.relpath(self.manifest.paths[path].worktree,
                                os.getcwd()) for path in opened_projects
            ]
            if not args:
                return
        all_projects = self.GetProjects(args,
                                        missing_ok=True,
                                        submodules_ok=opt.fetch_submodules)

        err_network_sync = False
        err_update_projects = False
        err_checkout = False

        self._fetch_times = _FetchTimes(self.manifest)
        if not opt.local_only:
            to_fetch = []
            now = time.time()
            if _ONE_DAY_S <= (now - rp.LastFetch):
                to_fetch.append(rp)
            to_fetch.extend(all_projects)
            to_fetch.sort(key=self._fetch_times.Get, reverse=True)

            fetched = self._Fetch(to_fetch, opt, err_event)

            _PostRepoFetch(rp, opt.repo_verify)
            if opt.network_only:
                # bail out now; the rest touches the working tree
                if err_event.isSet():
                    print('\nerror: Exited sync due to fetch errors.\n',
                          file=sys.stderr)
                    sys.exit(1)
                return

            # Iteratively fetch missing and/or nested unregistered submodules
            previously_missing_set = set()
            while True:
                self._ReloadManifest(manifest_name)
                all_projects = self.GetProjects(
                    args, missing_ok=True, submodules_ok=opt.fetch_submodules)
                missing = []
                for project in all_projects:
                    if project.gitdir not in fetched:
                        missing.append(project)
                if not missing:
                    break
                # Stop us from non-stopped fetching actually-missing repos: If set of
                # missing repos has not been changed from last fetch, we break.
                missing_set = set(p.name for p in missing)
                if previously_missing_set == missing_set:
                    break
                previously_missing_set = missing_set
                fetched.update(self._Fetch(missing, opt, err_event))

            # If we saw an error, exit with code 1 so that other scripts can check.
            if err_event.isSet():
                err_network_sync = True
                if opt.fail_fast:
                    print(
                        '\nerror: Exited sync due to fetch errors.\n'
                        'Local checkouts *not* updated. Resolve network issues & '
                        'retry.\n'
                        '`repo sync -l` will update some local checkouts.',
                        file=sys.stderr)
                    sys.exit(1)

        if self.manifest.IsMirror or self.manifest.IsArchive:
            # bail out now, we have no working tree
            return

        if self.UpdateProjectList(opt):
            err_event.set()
            err_update_projects = True
            if opt.fail_fast:
                print('\nerror: Local checkouts *not* updated.',
                      file=sys.stderr)
                sys.exit(1)

        err_results = []
        self._Checkout(all_projects, opt, err_event, err_results)
        if err_event.isSet():
            err_checkout = True
            # NB: We don't exit here because this is the last step.

        # If there's a notice that's supposed to print at the end of the sync, print
        # it now...
        if self.manifest.notice:
            print(self.manifest.notice)

        # If we saw an error, exit with code 1 so that other scripts can check.
        if err_event.isSet():
            print('\nerror: Unable to fully sync the tree.', file=sys.stderr)
            if err_network_sync:
                print('error: Downloading network changes failed.',
                      file=sys.stderr)
            if err_update_projects:
                print('error: Updating local project lists failed.',
                      file=sys.stderr)
            if err_checkout:
                print('error: Checking out local projects failed.',
                      file=sys.stderr)
                if err_results:
                    print('Failing repos:\n%s' % '\n'.join(err_results),
                          file=sys.stderr)
            print(
                'Try re-running with "-j1 --fail-fast" to exit at the first error.',
                file=sys.stderr)
            sys.exit(1)

        if not opt.quiet:
            print('repo sync has finished successfully.')
コード例 #28
0
 def _SaveJson(self, cache):
   try:
     with open(self._json, 'w') as fd:
       json.dump(cache, fd, indent=2)
   except (IOError, TypeError):
     platform_utils.remove(self._json, missing_ok=True)
コード例 #29
0
  def Execute(self, opt, args):
    if opt.jobs:
      self.jobs = opt.jobs
    if self.jobs > 1:
      soft_limit, _ = _rlimit_nofile()
      self.jobs = min(self.jobs, (soft_limit - 5) // 3)

    if opt.manifest_name:
      self.manifest.Override(opt.manifest_name)

    manifest_name = opt.manifest_name
    smart_sync_manifest_path = os.path.join(
        self.manifest.manifestProject.worktree, 'smart_sync_override.xml')

    if opt.clone_bundle is None:
      opt.clone_bundle = self.manifest.CloneBundle

    if opt.smart_sync or opt.smart_tag:
      manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path)
    else:
      if os.path.isfile(smart_sync_manifest_path):
        try:
          platform_utils.remove(smart_sync_manifest_path)
        except OSError as e:
          print('error: failed to remove existing smart sync override manifest: %s' %
                e, file=sys.stderr)

    err_event = multiprocessing.Event()

    rp = self.manifest.repoProject
    rp.PreSync()
    cb = rp.CurrentBranch
    if cb:
      base = rp.GetBranch(cb).merge
      if not base or not base.startswith('refs/heads/'):
        print('warning: repo is not tracking a remote branch, so it will not '
              'receive updates; run `repo init --repo-rev=stable` to fix.',
              file=sys.stderr)

    mp = self.manifest.manifestProject
    is_standalone_manifest = mp.config.GetString('manifest.standalone')
    if not is_standalone_manifest:
      mp.PreSync()

    if opt.repo_upgraded:
      _PostRepoUpgrade(self.manifest, quiet=opt.quiet)

    if not opt.mp_update:
      print('Skipping update of local manifest project.')
    elif not is_standalone_manifest:
      self._UpdateManifestProject(opt, mp, manifest_name)

    load_local_manifests = not self.manifest.HasLocalManifests
    use_superproject = git_superproject.UseSuperproject(opt, self.manifest)
    if self.manifest.IsMirror or self.manifest.IsArchive:
      # Don't use superproject, because we have no working tree.
      use_superproject = False
      print('Defaulting to no-use-superproject because there is no working tree.')
    superproject_logging_data = {
        'superproject': use_superproject,
        'haslocalmanifests': bool(self.manifest.HasLocalManifests),
        'hassuperprojecttag': bool(self.manifest.superproject),
    }
    if use_superproject:
      manifest_name = self._UpdateProjectsRevisionId(
          opt, args, load_local_manifests, superproject_logging_data) or opt.manifest_name

    if self.gitc_manifest:
      gitc_manifest_projects = self.GetProjects(args,
                                                missing_ok=True)
      gitc_projects = []
      opened_projects = []
      for project in gitc_manifest_projects:
        if project.relpath in self.gitc_manifest.paths and \
           self.gitc_manifest.paths[project.relpath].old_revision:
          opened_projects.append(project.relpath)
        else:
          gitc_projects.append(project.relpath)

      if not args:
        gitc_projects = None

      if gitc_projects != [] and not opt.local_only:
        print('Updating GITC client: %s' % self.gitc_manifest.gitc_client_name)
        manifest = GitcManifest(self.repodir, self.gitc_manifest.gitc_client_name)
        if manifest_name:
          manifest.Override(manifest_name)
        else:
          manifest.Override(self.manifest.manifestFile)
        gitc_utils.generate_gitc_manifest(self.gitc_manifest,
                                          manifest,
                                          gitc_projects)
        print('GITC client successfully synced.')

      # The opened projects need to be synced as normal, therefore we
      # generate a new args list to represent the opened projects.
      # TODO: make this more reliable -- if there's a project name/path overlap,
      # this may choose the wrong project.
      args = [os.path.relpath(self.manifest.paths[path].worktree, os.getcwd())
              for path in opened_projects]
      if not args:
        return
    all_projects = self.GetProjects(args,
                                    missing_ok=True,
                                    submodules_ok=opt.fetch_submodules)

    err_network_sync = False
    err_update_projects = False

    self._fetch_times = _FetchTimes(self.manifest)
    if not opt.local_only:
      with multiprocessing.Manager() as manager:
        with ssh.ProxyManager(manager) as ssh_proxy:
          # Initialize the socket dir once in the parent.
          ssh_proxy.sock()
          all_projects = self._FetchMain(opt, args, all_projects, err_event,
                                         manifest_name, load_local_manifests,
                                         ssh_proxy)

      if opt.network_only:
        return

      # If we saw an error, exit with code 1 so that other scripts can check.
      if err_event.is_set():
        err_network_sync = True
        if opt.fail_fast:
          print('\nerror: Exited sync due to fetch errors.\n'
                'Local checkouts *not* updated. Resolve network issues & '
                'retry.\n'
                '`repo sync -l` will update some local checkouts.',
                file=sys.stderr)
          sys.exit(1)

    if self.manifest.IsMirror or self.manifest.IsArchive:
      # bail out now, we have no working tree
      return

    if self.UpdateProjectList(opt):
      err_event.set()
      err_update_projects = True
      if opt.fail_fast:
        print('\nerror: Local checkouts *not* updated.', file=sys.stderr)
        sys.exit(1)

    err_update_linkfiles = not self.UpdateCopyLinkfileList()
    if err_update_linkfiles:
      err_event.set()
      if opt.fail_fast:
        print('\nerror: Local update copyfile or linkfile failed.', file=sys.stderr)
        sys.exit(1)

    err_results = []
    # NB: We don't exit here because this is the last step.
    err_checkout = not self._Checkout(all_projects, opt, err_results)
    if err_checkout:
      err_event.set()

    # If there's a notice that's supposed to print at the end of the sync, print
    # it now...
    if self.manifest.notice:
      print(self.manifest.notice)

    # If we saw an error, exit with code 1 so that other scripts can check.
    if err_event.is_set():
      print('\nerror: Unable to fully sync the tree.', file=sys.stderr)
      if err_network_sync:
        print('error: Downloading network changes failed.', file=sys.stderr)
      if err_update_projects:
        print('error: Updating local project lists failed.', file=sys.stderr)
      if err_update_linkfiles:
        print('error: Updating copyfiles or linkfiles failed.', file=sys.stderr)
      if err_checkout:
        print('error: Checking out local projects failed.', file=sys.stderr)
        if err_results:
          print('Failing repos:\n%s' % '\n'.join(err_results), file=sys.stderr)
      print('Try re-running with "-j1 --fail-fast" to exit at the first error.',
            file=sys.stderr)
      sys.exit(1)

    # Log the previous sync analysis state from the config.
    self.git_event_log.LogDataConfigEvents(mp.config.GetSyncAnalysisStateData(),
                                           'previous_sync_state')

    # Update and log with the new sync analysis state.
    mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
    self.git_event_log.LogDataConfigEvents(mp.config.GetSyncAnalysisStateData(),
                                           'current_sync_state')

    if not opt.quiet:
      print('repo sync has finished successfully.')