def Sync_LocalHalf()

in project.py [0:0]


  def Sync_LocalHalf(self, syncbuf, force_sync=False, submodules=False):
    """Perform only the local IO portion of the sync process.
       Network access is not required.
    """
    if not os.path.exists(self.gitdir):
      syncbuf.fail(self,
                   'Cannot checkout %s due to missing network sync; Run '
                   '`repo sync -n %s` first.' %
                   (self.name, self.name))
      return

    self._InitWorkTree(force_sync=force_sync, submodules=submodules)
    all_refs = self.bare_ref.all
    self.CleanPublishedCache(all_refs)
    revid = self.GetRevisionId(all_refs)

    # Special case the root of the repo client checkout.  Make sure it doesn't
    # contain files being checked out to dirs we don't allow.
    if self.relpath == '.':
      PROTECTED_PATHS = {'.repo'}
      paths = set(self.work_git.ls_tree('-z', '--name-only', '--', revid).split('\0'))
      bad_paths = paths & PROTECTED_PATHS
      if bad_paths:
        syncbuf.fail(self,
                     'Refusing to checkout project that writes to protected '
                     'paths: %s' % (', '.join(bad_paths),))
        return

    def _doff():
      self._FastForward(revid)
      self._CopyAndLinkFiles()

    def _dosubmodules():
      self._SyncSubmodules(quiet=True)

    head = self.work_git.GetHead()
    if head.startswith(R_HEADS):
      branch = head[len(R_HEADS):]
      try:
        head = all_refs[head]
      except KeyError:
        head = None
    else:
      branch = None

    if branch is None or syncbuf.detach_head:
      # Currently on a detached HEAD.  The user is assumed to
      # not have any local modifications worth worrying about.
      #
      if self.IsRebaseInProgress():
        syncbuf.fail(self, _PriorSyncFailedError())
        return

      if head == revid:
        # No changes; don't do anything further.
        # Except if the head needs to be detached
        #
        if not syncbuf.detach_head:
          # The copy/linkfile config may have changed.
          self._CopyAndLinkFiles()
          return
      else:
        lost = self._revlist(not_rev(revid), HEAD)
        if lost:
          syncbuf.info(self, "discarding %d commits", len(lost))

      try:
        self._Checkout(revid, quiet=True)
        if submodules:
          self._SyncSubmodules(quiet=True)
      except GitError as e:
        syncbuf.fail(self, e)
        return
      self._CopyAndLinkFiles()
      return

    if head == revid:
      # No changes; don't do anything further.
      #
      # The copy/linkfile config may have changed.
      self._CopyAndLinkFiles()
      return

    branch = self.GetBranch(branch)

    if not branch.LocalMerge:
      # The current branch has no tracking configuration.
      # Jump off it to a detached HEAD.
      #
      syncbuf.info(self,
                   "leaving %s; does not track upstream",
                   branch.name)
      try:
        self._Checkout(revid, quiet=True)
        if submodules:
          self._SyncSubmodules(quiet=True)
      except GitError as e:
        syncbuf.fail(self, e)
        return
      self._CopyAndLinkFiles()
      return

    upstream_gain = self._revlist(not_rev(HEAD), revid)

    # See if we can perform a fast forward merge.  This can happen if our
    # branch isn't in the exact same state as we last published.
    try:
      self.work_git.merge_base('--is-ancestor', HEAD, revid)
      # Skip the published logic.
      pub = False
    except GitError:
      pub = self.WasPublished(branch.name, all_refs)

    if pub:
      not_merged = self._revlist(not_rev(revid), pub)
      if not_merged:
        if upstream_gain:
          # The user has published this branch and some of those
          # commits are not yet merged upstream.  We do not want
          # to rewrite the published commits so we punt.
          #
          syncbuf.fail(self,
                       "branch %s is published (but not merged) and is now "
                       "%d commits behind" % (branch.name, len(upstream_gain)))
        return
      elif pub == head:
        # All published commits are merged, and thus we are a
        # strict subset.  We can fast-forward safely.
        #
        syncbuf.later1(self, _doff)
        if submodules:
          syncbuf.later1(self, _dosubmodules)
        return

    # Examine the local commits not in the remote.  Find the
    # last one attributed to this user, if any.
    #
    local_changes = self._revlist(not_rev(revid), HEAD, format='%H %ce')
    last_mine = None
    cnt_mine = 0
    for commit in local_changes:
      commit_id, committer_email = commit.split(' ', 1)
      if committer_email == self.UserEmail:
        last_mine = commit_id
        cnt_mine += 1

    if not upstream_gain and cnt_mine == len(local_changes):
      return

    if self.IsDirty(consider_untracked=False):
      syncbuf.fail(self, _DirtyError())
      return

    # If the upstream switched on us, warn the user.
    #
    if branch.merge != self.revisionExpr:
      if branch.merge and self.revisionExpr:
        syncbuf.info(self,
                     'manifest switched %s...%s',
                     branch.merge,
                     self.revisionExpr)
      elif branch.merge:
        syncbuf.info(self,
                     'manifest no longer tracks %s',
                     branch.merge)

    if cnt_mine < len(local_changes):
      # Upstream rebased.  Not everything in HEAD
      # was created by this user.
      #
      syncbuf.info(self,
                   "discarding %d commits removed from upstream",
                   len(local_changes) - cnt_mine)

    branch.remote = self.GetRemote(self.remote.name)
    if not ID_RE.match(self.revisionExpr):
      # in case of manifest sync the revisionExpr might be a SHA1
      branch.merge = self.revisionExpr
      if not branch.merge.startswith('refs/'):
        branch.merge = R_HEADS + branch.merge
    branch.Save()

    if cnt_mine > 0 and self.rebase:
      def _docopyandlink():
        self._CopyAndLinkFiles()

      def _dorebase():
        self._Rebase(upstream='%s^1' % last_mine, onto=revid)
      syncbuf.later2(self, _dorebase)
      if submodules:
        syncbuf.later2(self, _dosubmodules)
      syncbuf.later2(self, _docopyandlink)
    elif local_changes:
      try:
        self._ResetHard(revid)
        if submodules:
          self._SyncSubmodules(quiet=True)
        self._CopyAndLinkFiles()
      except GitError as e:
        syncbuf.fail(self, e)
        return
    else:
      syncbuf.later1(self, _doff)
      if submodules:
        syncbuf.later1(self, _dosubmodules)