def validate_revision(git_repo, revision)
      branches = git_repo.branches(:all => true)
      local_branches = branches.local
      remote_branches = branches.remote
      by_name = lambda { |item| item.name == revision }

      # determine if revision is a tag.
      remote_name = nil
      if git_repo.tags.any?(&by_name)
        if remote_branches.any?(&by_name)
          # note that git has some resolution scheme for ambiguous SHA, tag,
          # branch names but we do not support ambiguity.
          raise RetrieverError, "Ambiguous name is both a remote branch and a tag: #{revision.inspect}"
        elsif local_branches.any?(&by_name)
          # odd corner case of a name that once was a remote branch (now
          # deleted) that has become a tag instead. the user is not exactly
          # at fault here (aside from being indecisive) so let's attempt to
          # clean up after him. try switching to another local branch
          # (i.e. master) and then deleting the obsolete local branch.
          error_message = "Ambiguous name is both a local branch and a tag: #{revision.inspect}"
          if revision == DEFAULT_BRANCH_NAME
            # Darwin Awards winner; scraping with a tag named 'master' :@
            raise RetrieverError, error_message
          else
            begin
              # checkout master and delete obsolete local branch.
              git_repo.checkout_to(DEFAULT_BRANCH_NAME, :force => true)
              git_repo.spit_output("branch -D #{revision}")
            rescue ::RightGit::RightGitError
              # ignore failed attempt to recover; raise original error.
              raise RetrieverError, error_message
            end
          end
        end
      else
        # not a tag; SHA or branch.
        #
        # note that we could try to trivially determine if revision was a
        # SHA by matching the SHA1 pattern except that:
        #  1) git accepts partial SHAs so long as they uniquely distinguish
        #     a commit for checkout.
        #  2) a branch or tag could name could match the SHA pattern (i.e.
        #     40 hexadecimal characters) with no warnings from git. git will
        #     even allow a user to use a SHA as a tag name when that SHA
        #     exists (and may represent a different commit).
        # confusing tags with SHAs should be universally discouraged but we
        # need to be flexible here.
        #
        # a local branch may no longer exist remotely or may be behind or
        # have diverged from remote branch. handle all cases.
        remotes = remote_branches.select(&by_name)
        if remotes.size > 1
          # multiple remote branches exist (from different origins); branch
          # name is ambiguous.
          raise RetrieverError, "Ambiguous remote branch name: #{revision.inspect}"
        elsif remotes.size == 1
          # a remote branch exists.
          remote_name = remotes.first.fullname
        elsif local_branches.any?(&by_name)
          # local branch only; failure due to missing remote branch.
          #
          # note that obsolete local branches are not supported by retrieval
          # only because it would give the user a false positive.
          raise RetrieverError, "Missing remote branch: #{revision.inspect}."
        end # else a full or partial SHA or unknown revision
      end
      remote_name
    end
def validate_revision(git_repo, revision)
      branches = git_repo.branches(:all => true)
      local_branches = branches.local
      remote_branches = branches.remote
      by_name = lambda { |item| item.name == revision }

      # determine if revision is a tag.
      remote_name = nil
      if git_repo.tags.any?(&by_name)
        if remote_branches.any?(&by_name)
          # note that git has some resolution scheme for ambiguous SHA, tag,
          # branch names but we do not support ambiguity.
          raise RetrieverError, "Ambiguous name is both a remote branch and a tag: #{revision.inspect}"
        elsif local_branches.any?(&by_name)
          # odd corner case of a name that once was a remote branch (now
          # deleted) that has become a tag instead. the user is not exactly
          # at fault here (aside from being indecisive) so let's attempt to
          # clean up after him. try switching to another local branch
          # (i.e. master) and then deleting the obsolete local branch.
          error_message = "Ambiguous name is both a local branch and a tag: #{revision.inspect}"
          if revision == DEFAULT_BRANCH_NAME
            # Darwin Awards winner; scraping with a tag named 'master' :@
            raise RetrieverError, error_message
          else
            begin
              # checkout master and delete obsolete local branch.
              git_repo.checkout_to(DEFAULT_BRANCH_NAME, :force => true)
              git_repo.spit_output("branch -D #{revision}")
            rescue ::RightGit::RightGitError
              # ignore failed attempt to recover; raise original error.
              raise RetrieverError, error_message
            end
          end
        end
      else
        # not a tag; SHA or branch.
        #
        # note that we could try to trivially determine if revision was a
        # SHA by matching the SHA1 pattern except that:
        #  1) git accepts partial SHAs so long as they uniquely distinguish
        #     a commit for checkout.
        #  2) a branch or tag could name could match the SHA pattern (i.e.
        #     40 hexadecimal characters) with no warnings from git. git will
        #     even allow a user to use a SHA as a tag name when that SHA
        #     exists (and may represent a different commit).
        # confusing tags with SHAs should be universally discouraged but we
        # need to be flexible here.
        #
        # a local branch may no longer exist remotely or may be behind or
        # have diverged from remote branch. handle all cases.
        remotes = remote_branches.select(&by_name)
        if remotes.size > 1
          # multiple remote branches exist (from different origins); branch
          # name is ambiguous.
          raise RetrieverError, "Ambiguous remote branch name: #{revision.inspect}"
        elsif remotes.size == 1
          # a remote branch exists.
          remote_name = remotes.first.fullname
        elsif local_branches.any?(&by_name)
          # local branch only; failure due to missing remote branch.
          #
          # note that obsolete local branches are not supported by retrieval
          # only because it would give the user a false positive.
          raise RetrieverError, "Missing remote branch: #{revision.inspect}."
        end # else a full or partial SHA or unknown revision
      end
      remote_name
    end
Validates the given revision string to ensure it is safe and sane before
 attempting to use it.

 @param [::RightGit::Git::Repository] git_repo for validation
 @param [String] revision for validation

 @return [String] remote_name (for branch reset) or nil

 @raise [RetrieverError] on validation failure