#31 Get correct default branch
Merged 6 years ago by ralph. Opened 6 years ago by lsedlar.
lsedlar/pag get-default-branch  into  develop

file modified
+19 -17
@@ -18,12 +18,13 @@ 

  CONF_FILE = os.path.expanduser('~/.config/pag')

  

  

- def run(cmd, echo=True, graceful=True):

-     click.echo('  $ ' + " ".join(cmd))

+ def run(cmd, echo=True, graceful=True, silent=False):

+     if not silent:

+         click.echo('  $ ' + " ".join(cmd))

      proc = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.STDOUT)

      output, _ = proc.communicate()

      output = output.decode('utf-8')

-     if echo:

+     if echo and not silent:

          click.echo(DIM + output + RESET)

      if not graceful and proc.returncode != 0:

          sys.exit(1)
@@ -65,20 +66,21 @@ 

      return inner

  

  

- def get_default_upstream_branch(name):

-     url = 'https://pagure.io/api/0/projects'

-     response = requests.get(url, params=dict(pattern=name, fork=False))

-     if not bool(response):

-         raise IOError("Failed to talk to %r %r", (url, response))

-     data = response.json()

-     projects = data['projects']

-     if not projects:

-         raise ValueError("No such project %r" % name)

-     if len(projects) > 1:

-         raise ValueError("More than one project called %r found "

-                          "(%i of them, in fact)." % (name, len(projects)))

-     project = projects[0]

-     return project['default_branch']

+ def get_default_upstream_branch():

+     """The default branch is whatever HEAD points to in the remote repo.

+     Usually the main repo will be either `upstream` or `origin`, so try both.

+     Returns ``None`` if no default branch could be found.

+     """

+     # TODO We should instead use `git ls-remote --symref REMOTE_URL HEAD`, but

+     # that does not currently work.

+     #   https://pagure.io/pagure/issue/2955

+     for remote in ('upstream', 'origin'):

+         ref = '%s/HEAD' % remote

+         ret, stdout = run(['git', 'rev-parse', '--abbrev-ref', ref], silent=True)

+         if ret == 0:

+             real_ref = stdout.strip()

+             assert real_ref.startswith('%s/' % remote)

+             return real_ref[len(remote) + 1:]

  

  

  def get_current_local_branch():

file modified
+56 -3
@@ -8,12 +8,16 @@ 

  from pag import utils

  

  

- class TestGetCurrentBranch(unittest.TestCase):

+ class GitTestCase(unittest.TestCase):

+     """

+     A base class for tests that need a git repo. It creates a temporary repo

+     with a single commit for each test and changes to that directory.

+     """

  

-     def cmd(self, cmd, *args, **kwargs):

+     def cmd(self, cmd, cwd=None, *args, **kwargs):

          print('$ %s' % ' '.join(shlex.quote(x) for x in cmd))

          cp = subprocess.run(cmd, *args,

-                             cwd=self.repo,

+                             cwd=cwd or self.repo,

                              stdout=subprocess.PIPE,

                              stderr=subprocess.STDOUT,

                              universal_newlines=True,
@@ -34,6 +38,55 @@ 

      def tearDown(self):

          shutil.rmtree(self.repo)

  

+ 

+ class TestGetDefaultBranch(GitTestCase):

+     """

+     This test treats the inherited repo as upstream and clones it into a

+     separate directory, in which it runs the actual function. It can check out

+     a different branch in the "upstream" repo and thus effectively change the

+     default branch.

+     """

+ 

+     def setUp(self):

+         super().setUp()

+         self.clone = tempfile.mkdtemp(prefix='cloned_repo_')

+ 

+     def tearDown(self):

+         super().tearDown()

+         shutil.rmtree(self.clone)

+ 

+     def _clone_to(self, remote, branch):

+         if branch != 'master':

+             self.cmd(['git', 'checkout', '-b', branch])

+         self.cmd(['git', 'clone', self.repo, self.clone, '-o', remote])

+         os.chdir(self.clone)

+ 

+     def test_origin_master(self):

+         self._clone_to('origin', 'master')

+ 

+         self.assertEqual(utils.get_default_upstream_branch(), 'master')

+ 

+     def test_origin_develop(self):

+         self._clone_to('origin', 'develop')

+ 

+         self.assertEqual(utils.get_default_upstream_branch(), 'develop')

+ 

+     def test_upstream_master(self):

+         self._clone_to('upstream', 'master')

+ 

+         self.assertEqual(utils.get_default_upstream_branch(), 'master')

+ 

+     def test_upstream_develop(self):

+         self._clone_to('upstream', 'develop')

+ 

+         self.assertEqual(utils.get_default_upstream_branch(), 'develop')

+ 

+     def test_no_remote(self):

+         self.assertEqual(utils.get_default_upstream_branch(), None)

+ 

+ 

+ class TestGetCurrentBranch(GitTestCase):

+ 

      def test_single_branch(self):

          self.cmd(['git', 'checkout', '-b', 'test'])

          self.cmd(['git', 'commit', '--allow-empty', '-m', 'Dummy commit'])

The API does not provide this information, but we don't really need it.

In ideal word we could just do git ls-remote --symref GIT_URL HEAD and
get the information, but for some reason this does not currently work
with Pagure.

Default branch should be whatever HEAD points to in the remote repo, and
since we most likely work in a clone of it, the ref will exist locally
as well.

As an additional test case, this PR was submitted with pag pull-request -h lsedlar:get-default-branch using this patch.

Pull-Request has been merged by ralph

6 years ago
Metadata