Esempio n. 1
0
    def test_push_two_that_modify_same_file(self):
        '''
        Push performs a rebase if two commits touch the same file.
        This test verifies that code path works.
        '''

        oldlen = test_util.repolen(self.repo)
        oldtiphash = revsymbol(self.repo, 'default').node()

        changes = [('gamma', 'gamma', 'sometext')]
        newhash = self.commitchanges(changes)
        changes = [
            ('gamma', 'gamma', 'sometext\n moretext'),
            ('delta', 'delta', 'sometext\n moretext'),
        ]
        newhash = self.commitchanges(changes)

        repo = self.repo
        hg.update(repo, newhash)
        commands.push(repo.ui, repo)
        self.assertEqual(test_util.repolen(self.repo), oldlen + 2)

        # verify that both commits are pushed
        commit1 = revsymbol(self.repo, 'tip')
        self.assertEqual(commit1.files(), ['delta', 'gamma'])

        prefix = 'svn:' + self.repo.svnmeta().uuid
        self.assertEqual(util.getsvnrev(commit1),
                         prefix + '/branches/the_branch@6')
        commit2 = commit1.parents()[0]
        self.assertEqual(commit2.files(), ['gamma'])
        self.assertEqual(util.getsvnrev(commit2),
                         prefix + '/branches/the_branch@5')
Esempio n. 2
0
    def test_push_two_that_modify_same_file(self):
        '''
        Push performs a rebase if two commits touch the same file.
        This test verifies that code path works.
        '''

        oldlen = test_util.repolen(self.repo)
        oldtiphash = self.repo['default'].node()

        changes = [('gamma', 'gamma', 'sometext')]
        newhash = self.commitchanges(changes)
        changes = [('gamma', 'gamma', 'sometext\n moretext'),
                   ('delta', 'delta', 'sometext\n moretext'),
                  ]
        newhash = self.commitchanges(changes)

        repo = self.repo
        hg.update(repo, newhash)
        commands.push(repo.ui, repo)
        self.assertEqual(test_util.repolen(self.repo), oldlen + 2)

        # verify that both commits are pushed
        commit1 = self.repo['tip']
        self.assertEqual(commit1.files(), ['delta', 'gamma'])

        prefix = 'svn:' + self.repo.svnmeta().uuid
        self.assertEqual(util.getsvnrev(commit1),
                         prefix + '/branches/the_branch@6')
        commit2 = commit1.parents()[0]
        self.assertEqual(commit2.files(), ['gamma'])
        self.assertEqual(util.getsvnrev(commit2),
                         prefix + '/branches/the_branch@5')
Esempio n. 3
0
    def test_push_without_pushing_children(self):
        '''
        Verify that a push of a nontip node, keeps the tip child
        on top of the pushed commit.
        '''

        oldlen = test_util.repolen(self.repo)
        oldtiphash = revsymbol(self.repo, 'default').node()

        changes = [('gamma', 'gamma', 'sometext')]
        newhash1 = self.commitchanges(changes)

        changes = [('delta', 'delta', 'sometext')]
        newhash2 = self.commitchanges(changes)

        # push only the first commit
        repo = self.repo
        hg.update(repo, newhash1)
        commands.push(repo.ui, repo)
        self.assertEqual(test_util.repolen(self.repo), oldlen + 2)

        # verify that the first commit is pushed, and the second is not
        commit2 = revsymbol(self.repo, 'tip')
        self.assertEqual(commit2.files(), [
            'delta',
        ])
        self.assertEqual(util.getsvnrev(commit2), None)
        commit1 = commit2.parents()[0]
        self.assertEqual(commit1.files(), [
            'gamma',
        ])
        prefix = 'svn:' + self.repo.svnmeta().uuid
        self.assertEqual(util.getsvnrev(commit1),
                         prefix + '/branches/the_branch@5')
Esempio n. 4
0
 def test_push_two_revs_different_local_branch(self):
     def filectxfn(repo, memctx, path):
         return context.memfilectx(path=path,
                                   data=path,
                                   islink=False,
                                   isexec=False,
                                   copied=False)
     oldtiphash = self.repo['default'].node()
     ctx = context.memctx(self.repo,
                          (self.repo[0].node(), revlog.nullid, ),
                          'automated test',
                          ['gamma', ],
                          filectxfn,
                          'testy',
                          '2008-12-21 16:32:00 -0500',
                          {'branch': 'localbranch', })
     newhash = self.repo.commitctx(ctx)
     ctx = context.memctx(self.repo,
                          (newhash, revlog.nullid),
                          'automated test2',
                          ['delta', ],
                          filectxfn,
                          'testy',
                          '2008-12-21 16:32:00 -0500',
                          {'branch': 'localbranch', })
     newhash = self.repo.commitctx(ctx)
     repo = self.repo
     hg.update(repo, newhash)
     commands.push(repo.ui, repo)
     self.assertEqual(self.repo['tip'].parents()[0].parents()[0].node(), oldtiphash)
     self.assertEqual(self.repo['tip'].files(), ['delta', ])
     self.assertEqual(self.repo['tip'].manifest().keys(),
                      ['alpha', 'beta', 'gamma', 'delta'])
Esempio n. 5
0
    def test_push_without_pushing_children(self):
        '''
        Verify that a push of a nontip node, keeps the tip child
        on top of the pushed commit.
        '''

        oldlen = test_util.repolen(self.repo)
        oldtiphash = self.repo['default'].node()

        changes = [('gamma', 'gamma', 'sometext')]
        newhash1 = self.commitchanges(changes)

        changes = [('delta', 'delta', 'sometext')]
        newhash2 = self.commitchanges(changes)

        # push only the first commit
        repo = self.repo
        hg.update(repo, newhash1)
        commands.push(repo.ui, repo)
        self.assertEqual(test_util.repolen(self.repo), oldlen + 2)

        # verify that the first commit is pushed, and the second is not
        commit2 = self.repo['tip']
        self.assertEqual(commit2.files(), ['delta', ])
        self.assertEqual(util.getsvnrev(commit2), None)
        commit1 = commit2.parents()[0]
        self.assertEqual(commit1.files(), ['gamma', ])
        prefix = 'svn:' + self.repo.svnmeta().uuid
        self.assertEqual(util.getsvnrev(commit1),
                         prefix + '/branches/the_branch@5')
Esempio n. 6
0
    def commit(self, path=None, message=None, user=None):
        from mercurial import commands, hg, ui, error
        log.debug("Commit to Mercurial repository.")

        path = path or self.path
        message = message or self.message
        user = user or self.user

        strings = [user.first_name, '<%s>' % user.email]
        author = ' '.join(filter(None, strings)) #  Only if not empty

        # For some reason default push path is not set properly
        import configparser, codecs
        config = configparser.ConfigParser()

        with codecs.open(os.path.join(path, '.hg/hgrc'), 'r', 'utf-8') as f:
            try:
                config.read_file(f)
            except Exception as e:
                raise CommitToRepositoryException(str(e))

        default_path = config.get('paths', 'default')

        try:
            u = ui.ui()
            u.setconfig('paths', 'default', default_path)
            repo = hg.repository(u, path)
            commands.commit(u, repo, message=message, user=author)
            commands.push(u, repo)
            log.info(message)

        except Exception as e:
            raise CommitToRepositoryException(str(e))
Esempio n. 7
0
    def internal_push_over_svnserve(self, subdir='', commit=True):
        test_util.load_svndump_fixture(self.repo_path, 'simple_branch.svndump')
        open(os.path.join(self.repo_path, 'conf', 'svnserve.conf'),
             'w').write('[general]\nanon-access=write\n[sasl]\n')
        self.port = random.randint(socket.IPPORT_USERRESERVED, 65535)
        self.host = 'localhost'
        args = ['svnserve', '--daemon', '--foreground',
                '--listen-port=%d' % self.port,
                '--listen-host=%s' % self.host,
                '--root=%s' % self.repo_path]

        svnserve = subprocess.Popen(args, stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)
        self.svnserve_pid = svnserve.pid
        try:
            time.sleep(2)
            import shutil
            shutil.rmtree(self.wc_path)
            commands.clone(self.ui(),
                           'svn://%s:%d/%s' % (self.host, self.port, subdir),
                           self.wc_path, noupdate=True)

            repo = self.repo
            old_tip = repo['tip'].node()
            expected_parent = repo['default'].node()
            def file_callback(repo, memctx, path):
                if path == 'adding_file':
                    return context.memfilectx(path=path,
                                              data='foo',
                                              islink=False,
                                              isexec=False,
                                              copied=False)
                raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
            ctx = context.memctx(repo,
                                 parents=(repo['default'].node(), node.nullid),
                                 text='automated test',
                                 files=['adding_file'],
                                 filectxfn=file_callback,
                                 user='******',
                                 date='2008-10-07 20:59:48 -0500',
                                 extra={'branch': 'default',})
            new_hash = repo.commitctx(ctx)
            if not commit:
                return # some tests use this test as an extended setup.
            hg.update(repo, repo['tip'].node())
            oldauthor = repo['tip'].user()
            commands.push(repo.ui, repo)
            tip = self.repo['tip']
            self.assertNotEqual(oldauthor, tip.user())
            self.assertNotEqual(tip.node(), old_tip)
            self.assertEqual(tip.parents()[0].node(), expected_parent)
            self.assertEqual(tip['adding_file'].data(), 'foo')
            self.assertEqual(tip.branch(), 'default')
            # unintended behaviour:
            self.assertNotEqual('an_author', tip.user())
            self.assertEqual('(no author)', tip.user().rsplit('@', 1)[0])
        finally:
            # TODO: use svnserve.kill() in Python >2.5
            test_util.kill_process(svnserve)
Esempio n. 8
0
def push_to_try(ui, repo, server, message=None):

    nodate = ui.configbool('push-to-try', 'nodate')

    if not message or 'try:' not in message:
        ui.status("STOP! A commit message with try syntax is required.\n")
        return

    cctx = context.workingctx(repo)
    status = repo.status()

    if status.modified + status.added + status.removed:
        ui.status('The following will be pushed to %s:\n' % server)
        # TODO: Achieve this by re-using the status call above to avoid the
        # cost of running it twice.
        commands.status(ui, repo)

    preserve_ctx = preservefilectx(cctx)

    def mk_memfilectx(repo, memctx, path):
        if path not in status.removed:
            return preserve_ctx(repo, memctx, path)
        return None

    # Invent a temporary commit with our message.
    ui.status("Creating temporary commit for remote...\n")
    mctx = context.memctx(repo,
                          repo.dirstate.parents(),
                          message,
                          cctx.files(),
                          mk_memfilectx,
                          date="0 0" if nodate else None)

    # These messages are expected when we abort our transaction, but aren't
    # helpful to a user and may be misleading so we surpress them here.
    filtered_phrases = {_("transaction abort!\n"), _("rollback completed\n")}

    def filtered_warn(*msgs, **opts):
        if msgs:
            filtered = [m for m in msgs if m not in filtered_phrases]
        if filtered:
            ui.warn(*filtered, **opts)

    lock = tr = None
    try:
        lock = repo.lock()
        tr = repo.transaction('push-to-try', report=filtered_warn)
        m = mctx.commit()
        # Push to try.
        commands.push(ui, repo, server, force=True, rev=[repo[m].rev()])
        ui.status('push complete\n')
        # And rollback to the previous state.
        tr.abort()
    finally:
        if tr:
            tr.release()
        if lock:
            lock.release()
        ui.status("temporary commit removed, repository restored\n")
def push_to_try(ui, repo, server, message=None):

    nodate = ui.configbool('push-to-try', 'nodate')

    if not message or 'try:' not in message:
        ui.status("STOP! A commit message with try syntax is required.\n")
        return

    cctx = context.workingctx(repo)
    status = repo.status()

    if status.modified + status.added + status.removed:
        ui.status('The following will be pushed to %s:\n' % server)
        # TODO: Achieve this by re-using the status call above to avoid the
        # cost of running it twice.
        commands.status(ui, repo)

    preserve_ctx = preservefilectx(cctx)
    def mk_memfilectx(repo, memctx, path):
        if path not in status.removed:
            return preserve_ctx(repo, memctx, path)
        return None

    # Invent a temporary commit with our message.
    ui.status("Creating temporary commit for remote...\n")
    mctx = context.memctx(repo,
                          repo.dirstate.parents(),
                          message,
                          cctx.files(),
                          mk_memfilectx,
                          date="0 0" if nodate else None)

    # These messages are expected when we abort our transaction, but aren't
    # helpful to a user and may be misleading so we surpress them here.
    filtered_phrases = {_("transaction abort!\n"),
                        _("rollback completed\n")}
    def filtered_warn(*msgs, **opts):
        if msgs:
            filtered = [m for m in msgs if m not in filtered_phrases]
        if filtered:
            ui.warn(*filtered, **opts)

    lock = tr = None
    try:
        lock = repo.lock()
        tr = repo.transaction('push-to-try', report=filtered_warn)
        m = mctx.commit()
        # Push to try.
        commands.push(ui, repo, server, force=True, rev=[repo[m].rev()])
        ui.status('push complete\n')
        # And rollback to the previous state.
        tr.abort()
    finally:
        if tr:
            tr.release()
        if lock:
            lock.release()
        ui.status("temporary commit removed, repository restored\n")
 def function(tree, destpath, opts):
     try:
         commands.push(ui, tree.getrepo(ui), destpath, **opts)
     except Exception, err:
         ui.warn(_("skipped: %s\n") % err)
         try:
             tree.repo.transaction().__del__()
         except AttributeError:
             pass
Esempio n. 11
0
def _cycle(ui, root, commitopts, fetchopts, pushopts):
    """Run a single 'commit, fetch, push' cycle"""

    repo = hg.repository(ui, path=root)
    ui.status("sync: commit working copy changes\n")
    commands.commit(ui, repo, **commitopts)
    ui.status("sync: fetch changes from other repository\n")
    fetch(ui, repo, **fetchopts)
    ui.status("sync: push local changes to other repository\n")
    commands.push(ui, repo, **pushopts)
Esempio n. 12
0
File: hg.py Progetto: dahool/vertaal
 def submit(self, auth, msg):
     _user_auth = auth
     logger.debug("Perform submit %s [%s]" % (self.location, msg))
     self._send_callback(self.callback_on_action_notify,_('Checking in'))
     commands.commit(self.repo.ui, self.repo, 
                     message=msg.encode('utf-8'),
                     addremove=True, logfile=None, 
                     date=None)
     commands.push(self.repo.ui, self.repo, force=False, rev=None)
     return 0
Esempio n. 13
0
File: try.py Progetto: nwgh/mozdev
def run_try(ui, repo, *args, **opts):
    """Push the current head to try
    """
    if not opts['build'] or not opts['platform']:
        raise util.Abort('Both -b and -p are required')

    # We rely on the try server to validate anything beyond that simple
    # check above, so let's just blindly go about our business!

    tryopts = []
    tryopts.append('-b')
    tryopts.extend(opts['build'])
    tryopts.append('-p')
    tryopts.extend(opts['platform'])
    if opts.get('unit'):
        tryopts.append('-u')
        tryopts.extend(opts['unit'])
    if opts.get('talos'):
        tryopts.append('-t')
        tryopts.extend(opts['talos'])

    trymsg = 'try: %s' % (' '.join(tryopts),)

    if repo[None].dirty():
        raise util.Abort('You have outstanding changes')

    try:
        strip = extensions.find('strip')
    except KeyError:
        ui.warn('strip extension not found, use the following syntax:\n')
        ui.write('%s\n' % (trymsg,))
        return

    ui.write('setting try selections...\n')

    # This next bit here is a hack to get an empty commit
    cwd = os.getcwd()
    junkfile = tempfile.mktemp(prefix='hgjunk', dir='')
    os.chdir(repo.root)
    file(junkfile, 'w').close()
    commands.add(ui, repo, junkfile)
    commands.commit(ui, repo, message='add junk file (will be gone)')
    commands.remove(ui, repo, junkfile)
    commands.commit(ui, repo, amend=True, message=trymsg, logfile=None)
    os.chdir(cwd)

    # Get the revision of our try commit so we can strip it later
    node = repo[None].p1().hex()

    ui.write('pushing to try...\n')
    commands.push(ui, repo, 'try', force=True)

    # Now we must clean up after ourslves by stripping the try commit
    strip.stripcmd(ui, repo, node, rev=[], no_backup=True)
Esempio n. 14
0
 def commit(self, message='',stdout=None):
     """
     Commit all changes into hg repository
     Note that local repo must be setup for access without key,
     and commit must not create new head, because push is not forced
     """
     u, r = self._hg(stdout)
     commands.addremove(u, r)
     commands.commit(u, r, message=message)
     commands.push(u, r)
     del u, r
Esempio n. 15
0
def pushall(ui, repo, **opts):
    """The Publishall core function. Makes your life easier."""
    repos = ui.configitems('paths')
    if not repos:
        ui.warn("No paths defined in your hgrc. Pushall aborted.\n")
    ui.status("%s paths found\n" % len(repos))
    for path in repos:
        ui.status("* pushing to %s\n" % path[0])
        try:
            commands.push(ui, repo, path[1], **opts)
        except Exception, e:
            print e
Esempio n. 16
0
    def test_update_after_push(self):
        repo = self.repo
        ui = repo.ui

        ui.setconfig(
            'hooks', 'debug-hgsubversion-between-push-and-pull-for-tests',
            lambda ui, repo, hooktype: self.add_svn_rev(
                self.repo_path, {'trunk/racey_file': 'race conditions suck'}))

        self.test_push_to_branch(push=False)
        commands.push(ui, repo)
        newctx = revsymbol(self.repo, '.')
        self.assertNotEqual(newctx.node(), revsymbol(self.repo, 'tip').node())
        self.assertEqual(newctx['adding_file'].data(), 'foo')
        self.assertEqual(newctx.branch(), 'the_branch')
Esempio n. 17
0
    def test_update_after_push(self):
        repo = self.repo
        ui = repo.ui

        ui.setconfig('hooks',
                     'debug-hgsubversion-between-push-and-pull-for-tests',
                     lambda ui, repo, hooktype: self.add_svn_rev(
                         self.repo_path,
                         {'trunk/racey_file': 'race conditions suck'}))

        self.test_push_to_branch(push=False)
        commands.push(ui, repo)
        newctx = self.repo['.']
        self.assertNotEqual(newctx.node(), self.repo['tip'].node())
        self.assertEqual(newctx['adding_file'].data(), 'foo')
        self.assertEqual(newctx.branch(), 'the_branch')
Esempio n. 18
0
 def pushrevisions(self, stupid=False, expected_extra_back=0):
     before = len(self.repo)
     self.repo.ui.setconfig("hgsubversion", "stupid", str(stupid))
     res = commands.push(self.repo.ui, self.repo)
     after = len(self.repo)
     self.assertEqual(expected_extra_back, after - before)
     return res
Esempio n. 19
0
 def pushrevisions(self, expected_extra_back=0):
     before = repolen(self.repo)
     self.repo.ui.setconfig('hgsubversion', 'stupid', str(self.stupid))
     res = commands.push(self.repo.ui, self.repo)
     after = repolen(self.repo)
     self.assertEqual(expected_extra_back, after - before)
     return res
Esempio n. 20
0
 def pushrevisions(self, expected_extra_back=0):
     before = repolen(self.repo)
     self.repo.ui.setconfig('hgsubversion', 'stupid', str(self.stupid))
     res = commands.push(self.repo.ui, self.repo)
     after = repolen(self.repo)
     self.assertEqual(expected_extra_back, after - before)
     return res
Esempio n. 21
0
def post_push(ui, repo, pats, opts, *args, **kwargs):
    dest = pats and pats[0]
    dest = ui.expandpath(dest or 'default-push', dest or 'default')
    if 'bitbucket.org' in dest:
        github = ui.config('paths', 'github')
        if github:
            return commands.push(ui, repo, github, **opts)
        ui.warn('no github mirror!?\n')
Esempio n. 22
0
def post_push(ui, repo, pats, opts, *args, **kwargs):
    dest = pats and pats[0]
    dest = ui.expandpath(dest or 'default-push', dest or 'default')
    if 'bitbucket.org' in dest:
        github = ui.config('paths', 'github')
        if github:
            return commands.push(ui, repo, github, **opts)
        ui.warn('no github mirror!?\n')
Esempio n. 23
0
    def test_push_two_revs_different_local_branch(self):
        def filectxfn(repo, memctx, path):
            return compathacks.makememfilectx(repo,
                                              memctx=memctx,
                                              path=path,
                                              data=path,
                                              islink=False,
                                              isexec=False,
                                              copied=False)

        oldtiphash = revsymbol(self.repo, 'default').node()
        lr = self.repo
        ctx = context.memctx(lr, (
            lr[0].node(),
            revlog.nullid,
        ), 'automated test', [
            'gamma',
        ], filectxfn, 'testy', '2008-12-21 16:32:00 -0500', {
            'branch': 'localbranch',
        })
        newhash = lr.commitctx(ctx)
        ctx = context.memctx(lr, (newhash, revlog.nullid), 'automated test2', [
            'delta',
        ], filectxfn, 'testy', '2008-12-21 16:32:00 -0500', {
            'branch': 'localbranch',
        })
        newhash = lr.commitctx(ctx)
        repo = self.repo
        hg.update(repo, newhash)
        commands.push(repo.ui, repo)
        self.assertEqual(
            revsymbol(self.repo, 'tip').parents()[0].parents()[0].node(),
            oldtiphash)
        self.assertEqual(revsymbol(self.repo, 'tip').files(), [
            'delta',
        ])
        self.assertEqual(sorted(revsymbol(self.repo, 'tip').manifest().keys()),
                         ['alpha', 'beta', 'delta', 'gamma'])
Esempio n. 24
0
    def create_repo(self, dest, ui):
        vct = 'http://hg.mozilla.org/hgcustom/version-control-tools'
        commands.clone(ui, vct, dest=os.path.join(dest, 'vct.hg'))

        ui.setconfig('extensions', 'pushlog',
                     os.path.join(dest, 'vct.hg/hgext/pushlog'))

        srcdir = os.path.join(dest, 'test')
        destdir = os.path.join(dest, 'testwork')

        if not os.path.exists(srcdir):
            os.makedirs(srcdir)

        commands.init(ui, srcdir)
        commands.init(ui, destdir)

        repo = hg.repository(ui, destdir)

        myfile1 = os.path.join(destdir, 'myfile1')
        myfile2 = os.path.join(destdir, 'myfile2')
        for i in range(5):
            with open(myfile1, 'a') as In:
                In.write(str(i))
            with open(myfile2, 'a') as In:
                In.write(str(i))
            commands.commit(ui,
                            repo,
                            myfile1,
                            myfile2,
                            message='message' + str(i),
                            user='******',
                            addremove=True)
            commands.push(ui, repo, dest=srcdir)
            time.sleep(1.01)

        return srcdir
Esempio n. 25
0
def post_push(ui, repo, pats, opts, *args, **kwargs):
    """ Push to Github after pushing to BitBucket """

    dest = pats and pats[0]
    dest = ui.expandpath(dest or 'default-push', dest or 'default')

    if 'bitbucket.org' in dest:
        dest = dest.rstrip('/')
        reponame = dest.split('/')[-1]
        username = dest.split('/')[-2]

        github = 'git+ssh://[email protected]/{username}/{reponame}.git'
        github = github.format(username=username, reponame=reponame)

        # Move "master" bookmark to point to tip
        commands.bookmark(ui, repo, mark='master', rev='tip', force=True)

        return commands.push(ui, repo, github, **opts)
 def push_reviewed(self):
     push_result = commands.push(self.ui,
                                 self.repo,
                                 self.rbrepo.path,
                                 new_branch=True)
     self.ui.status(_("Push result %d\n") % push_result)
     if (push_result != 0):
         if (push_result == 1):
             self.ui.status(
                 _("Nothing to push. Push command returned: %d\n") %
                 push_result)
         else:
             self.ui.status(
                 _("Cannot push. Please resubmit review request. Push command returned: %d\n"
                   ) % push_result)
             raise util.Abort(
                 "Cannot push. Please resubmit review request. Push command returned: %d"
                 % push_result)
def pushtree(ui, repo, tree=None, rev=None, **opts):
    """Push changesets to a Mozilla repository.

    If only the tree argument is defined, we will attempt to push the current
    tip to the repository specified. This may fail due to pushed mq patches,
    local changes, etc. Please note we only attempt to push the current tip and
    it's ancestors, not all changesets not in the remote repository. This is
    different from the default behavior of |hg push| and is the distinguishing
    difference from that command.

    If you would like to push a non-active head, specify it with -r REV. For
    example, if you are currently on mozilla-central but wish to push inbound
    to mozilla-inbound, run `hg pushtree -r inbound/default inbound`.
    """
    if not tree:
        raise util.Abort(_('A tree must be specified.'))

    tree, uri = resolve_trees_to_uris([tree], write_access=True)[0]

    if not uri:
        raise util.Abort("Don't know about tree: %s" % tree)

    return push(ui, repo, rev=[rev], dest=uri)
Esempio n. 28
0
 def push(self, wire, revisions, dest_path, hooks=True,
          push_branches=False):
     repo = self._factory.repo(wire)
     baseui = self._factory._create_config(wire['config'], hooks=hooks)
     commands.push(baseui, repo, dest=dest_path, rev=revisions,
                   new_branch=push_branches)
Esempio n. 29
0
def pushq(ui, repo, dest=None, **opts):
    """Runs the hg push command for the patch queue repo of a regular repo"""

    q = qrepo(ui, repo)
    commands.push(ui, hg.repository(q.path), dest, **opts)
Esempio n. 30
0
def tclose(ui, repo, *args, **opts):
  """ close the current topic branch and push to the central repository """

  mustBeTopicRepo(repo)

  # Sanity check
  if not isClean(ui, repo):
    return 1

  if args:
    branches = args
  else:
    if not onTopicBranch(ui, repo):
      return 1
    branches = [repo.dirstate.branch()]

  if 'tmenu' in opts:
    if ui.prompt("Branch '%s': close it?" % branches[0]).upper() != 'Y':
      return 1
    opts = { 'nopull':False, 'nopush':False }

  pulled = False # only pull once

  for branch in branches:

    # Pull new changes from the central repo to avoid multiple-heads problem
    if not opts['nopull'] and not pulled:
      if tryCommand(ui, "pull", lambda:commands.pull(ui, repo, **opts) >= 2):
        return 1
      pulled = True

    # Can't close already closed branches, nor any of the special branches
    if not repo.branchheads(branch) or branch in repo.topicSpecialBranches:
      ui.warn("Error: %s is not an open topic branch\n" % branch)
      return 1

    # Now update to the head of the branch being closed
    if repo.dirstate.parents()[0] not in repo.branchheads(branch):
      if tryCommand(ui, "update %s" % quoteBranch(branch), lambda:commands.update(ui, repo, node=branch)):
        return 1

    # Unlike a normal hg commit, if no text is specified we supply a reasonable default.
    branch = repo.dirstate.branch()
    text = opts.get('message')
    if text is None:
      text = "Closing %s" % branch

    # Close it
    if tryCommand(ui, "commit --close-branch", lambda:repo.commit(text, extra = {'close':'True'}) is None):
      return 1

    # Aditionally, for this to not be considered a "head" it has to have a
    # child commit. So we have to merge into prod. First, update.
    #
    if tryCommand(ui, "update %s" % repo.topicProdBranch, lambda:commands.update(ui, repo, node=repo.topicProdBranch)):
      return 1

    # Now merge, ignoring all conflicts.
    mergeOpts = copy.deepcopy(opts)
    mergeOpts['tool'] = "internal:fail"
    mergeOpts['noninteractive'] = True
    # Ignore return value... ok if merge fails
    tryCommand(ui, "merge -r %s" % quoteBranch(branch), 
               lambda:commands.merge(ui, repo, node=branch, **mergeOpts),
               repo = repo)

    # Revert all files to prod (regardless of what happened on the branch)
    revertOpts = copy.deepcopy(opts)
    revertOpts['all'] = True
    revertOpts['rev'] = "."
    if tryCommand(ui, "revert -a -r .", lambda:commands.revert(ui, repo, **revertOpts), repo = repo):
      return 1

    # Were there any merge conflicts?
    resolveOpts = copy.deepcopy(opts)
    resolveOpts['list'] = True
    if tryCommand(ui, "resolve -l", lambda:commands.resolve(ui, repo, **resolveOpts), repo = repo):
      return 1

    # Anything that had a merge conflict, mark it resolved (by the revert)
    if ui.lastTryCommandOutput != '':
      resolveOpts = copy.deepcopy(opts)
      resolveOpts['all'] = True
      resolveOpts['mark'] = True
      if tryCommand(ui, "resolve -a -m", lambda:commands.resolve(ui, repo, **resolveOpts), repo = repo):
        return 1

    # Commit the merge
    if tryCommand(ui, "commit", lambda:repo.commit(text) is None):
      return 1

  # And push.
  if not opts['nopush']:
    pushOpts = copy.deepcopy(opts)
    if 'message' in pushOpts:
      del pushOpts['message']
    pushOpts['force'] = True
    nameSet = set()
    for name, path in ui.configitems("paths"):
      nameSet.add(name)
    if tryCommand(ui, "push -f -b %s -b %s default" % (quoteBranch(branch), repo.topicProdBranch), 
                  lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), **pushOpts), 
                  repo=repo) > 1:
      return 1
    if "dev" in nameSet:
      if tryCommand(ui, "push -f -b %s -b %s dev" % (quoteBranch(branch), repo.topicProdBranch), 
                    lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="dev", **pushOpts), 
                    repo=repo) > 1:
        return 1
    if "stage" in nameSet:
      if tryCommand(ui, "push -f -b %s -b %s stage" % (quoteBranch(branch), repo.topicProdBranch), 
                    lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="stage", **pushOpts), 
                    repo=repo) > 1:
        return 1
    if "prod" in nameSet:
      if tryCommand(ui, "push -f -b %s -b %s prod" % (quoteBranch(branch), repo.topicProdBranch), 
                    lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="prod", **pushOpts), 
                    repo=repo) > 1:
        return 1

  ui.status("Done.\n")
Esempio n. 31
0
def sync_hg(hg_interface, local_repo_path, remote_repo_path=None):
    if remote_repo_path and not os.path.exists(remote_repo_path):
        #remote_repo_path does not exist
        #could sync with default source (e.g. github) here
        remote_repo_path = None

    #first pull down any changes that may exist on remote
    repo = hg.repository(hg_interface, local_repo_path)
    hg_interface.pushbuffer()
    commands.pull(hg_interface, repo, remote_repo_path)
    result = hg_interface.popbuffer()
    #hg_interface won't catch all of the output of a pull
    #if there were changes in the pull, it gets the line:
    #(run 'hg update' to get a working copy)
    #
    #if not, only has:
    # pulling from /media/CHARLES/charles

    #keep track if we find something that changes
    #so that we can pause at the end
    #otherwise we should just move on automatically
    changes = False

    print("%s" % result)
    lines = result.splitlines()
    if len(lines) > 1:
        #changes = True
        need_update = False

        for line in lines:
            #sometimes might be only 2 lines
            #sometimes might be 3:
            #['pulling from /media/charles/CHARLES/moments', 'updating bookmark master', "(run 'hg update' to get a working copy)"]
            if re.search('hg update', line):
                print("updating")
                hg_interface.pushbuffer()
                commands.update(hg_interface, repo)
                result = hg_interface.popbuffer()
                print("%s" % result)
                response = hg_interface.prompt("everything ok? (ctl-c to exit)",
                                            default='y')
                print("moving on then...")
                need_update = True

        if not need_update:
            #if we didn't update, the lines must be telling us
            #something else needs to happen...
            #must be a merge:
            print(lines)
            print("merge detected, all yours:")
            print("cd %s" % local_repo_path)
            exit()

    #at this point all changes from remote media should be applied locally
    #now we should check if we have any changes here:
    hg_interface.pushbuffer()
    commands.status(hg_interface, repo)
    result = hg_interface.popbuffer()
    if result:
        print("looks like there are some local changes:")
        print(result)
        changes = True

        new_files = False
        for line in result.splitlines():
            if line.startswith('?'):
                new_files = True
        if new_files:
            print("new files found")
            response = hg_interface.prompt("would you like to add the new files?", default='y')
            if response == 'y':
                commands.add(hg_interface, repo)


        response = hg_interface.prompt("log (ctl-c to exit):", default='')
        commands.commit(hg_interface, repo, message=response)

    #push changes:
    print("hg push %s" % remote_repo_path)
    commands.push(hg_interface, repo, remote_repo_path)

    lines = result.splitlines()
    if len(lines) > 1:
        changes = True

    #only do this if remote repo exists:
    if remote_repo_path:
        #on remote repo,
        remote_repo = hg.repository(hg_interface, remote_repo_path)
        #update
        print("updating remote:")
        hg_interface.pushbuffer()
        commands.update(hg_interface, remote_repo)
        result = hg_interface.popbuffer()
        print("%s" % result)

        #show remote status
        commands.status(hg_interface, remote_repo)
    else:
        print("skipping remote update: %s" % remote_repo_path)
        #pass



    if changes:
        response = hg_interface.prompt("everything ok? (ctl-c to exit)",
                                    default='y')
def push_to_try(ui, repo, server, message=None):

    nodate = ui.configbool(b'push-to-try', b'nodate')

    if not server:
        if b'try' in ui.paths:
            server = b'try'
        else:
            server = b'ssh://hg.mozilla.org/try'

    if not message:
        ui.status(b"STOP! A commit message is required.\n")
        return

    cctx = context.workingctx(repo)
    if b'try_task_config.json' not in cctx and b'try:' not in message:
        ui.status(b"STOP! Either try_task_config.json must be added or the commit "
                  b"message must contain try syntax.\n")
        return

    if b'try_task_config.json' in cctx:
        data = repo.wvfs.tryread(b'try_task_config.json')
        try:
            # data could be an empty string if tryread failed, which will
            # produce a ValueError here.
            data = json.loads(data)
        except ValueError as e:
            ui.status(b"Error reading try_task_config.json: could not decode as JSON\n")
            return

    # Invent a temporary commit with our message.
    ui.status(b"Creating temporary commit for remote...\n")
    status = repo.status()
    if status.modified + status.added + status.removed:
        # TODO: Achieve this by re-using the status call above to avoid the
        # cost of running it twice.
        commands.status(ui, repo)

    preserve_ctx = preservefilectx(cctx)
    def mk_memfilectx(repo, memctx, path):
        if path not in status.removed:
            return preserve_ctx(repo, memctx, path)
        return None

    mctx = context.memctx(repo,
                          repo.dirstate.parents(),
                          message,
                          cctx.files(),
                          mk_memfilectx,
                          date=b"0 0" if nodate else None)

    # These messages are expected when we abort our transaction, but aren't
    # helpful to a user and may be misleading so we surpress them here.
    filtered_phrases = {_(b"transaction abort!\n"),
                        _(b"rollback completed\n")}
    def filtered_warn(*msgs, **opts):
        if msgs:
            filtered = [m for m in msgs if m not in filtered_phrases]
        if filtered:
            ui.warn(*filtered, **opts)

    lock = tr = None
    try:
        lock = repo.lock()
        tr = repo.transaction(b'push-to-try', report=filtered_warn)
        m = mctx.commit()
        # Push to try.
        commands.push(ui, repo, server, force=True, rev=[repo[m].rev()])
        ui.status(b'push complete\n')
        # And rollback to the previous state.
        tr.abort()
    finally:
        if tr:
            tr.release()
        if lock:
            lock.release()
        ui.status(b"temporary commit removed, repository restored\n")
Esempio n. 33
0
def trychooser_command(ui, repo, *args, **opts):
    from mercurial import extensions, commands, util
    try:
        from mercurial import phases
    except:
        pass # older version with no phases

    if not sys.stdin.isatty():
        # rxvt on Windows disables ui.prompt, but installing our own seems to work
        def ui_prompt(prompt, default):
            sys.stdout.write(prompt)
            sys.stdout.write(" ")
            sys.stdout.flush()
            response = sys.stdin.readline().rstrip()
            if response == '':
                return default
            return response
        ui.prompt = ui_prompt

    display_only = opts['nopush']
    try:
        mq = extensions.find('mq')
    except KeyError:
        display_only = True
        ui.warn("Warning: mq hasn't been found, this is going to print the syntax only.\n")

    if repo[None].dirty():
        raise util.Abort("local changes found, refresh first")

    if opts.get('message'):
        msg = opts.get('message')
        if msg.find('try:') == -1:
            msg = 'try: ' + msg
    elif not menu or opts['question']:
        question(ui, headers, data['questions'])
        msg = "try: " + generateTrySyntax(headers, data['syntax'])
    else:
        syntaxGenerator = lambda h: generateTrySyntax(h, data['syntax'])
        msg = menu({ "syntaxGenerator": syntaxGenerator }, headers, ui)

    if opts['desc']:
        msg = opts['desc'] + ", " + msg

    #bugnum = suggest_results_bug(ui, repo)
    #if bugnum:
    #  msg += ' --post-to-bugzilla Bug %s' % bugnum

    if display_only:
        ui.write("Use the following try message:\n%s\n" % msg)
        return

    ui.write("The following try message is going to be used:\n%s\n" % msg)

    ui.write("Create the trychooser mq entry...\n")
    mq.new(ui, repo, 'trychooser', message=msg)

    ui.write("Push to try server...\n")
    try:
        commands.push(ui, repo, opts['server'], force=True,
                      rev=[repo['.'].rev()])

        # try server is running an old mercurial version that doesn't support
        # phases, so is assumed to be publishing. Undo the effects.
        lock = repo.lock()
        try:
            draft = phases.phasenames.index('draft')
            phases.retractboundary(repo, draft, [ repo.mq.applied[0].node ])
        except:
            pass # probably running under pre-phase version
        finally:
            lock.release()

    finally:
        mq.pop(ui, repo)
        mq.delete(ui, repo, 'trychooser')
Esempio n. 34
0
def tpush(ui, repo, *args, **opts):
  """ Push current branch to dev, stage, or production (and merge if prod). """

  mustBeTopicRepo(repo)

  # Sanity checks
  if not(onTopicBranch(ui, repo) and isClean(ui, repo)):
    return 1
  topicBranch = repo.dirstate.branch()

  # If called from the menu, allow user to choose target branch
  if 'tmenu' in opts:
    resp = ui.prompt("Push to which machine(es) [dsp], or blank to just share:", "")

    for c in resp:
      if c.upper() not in ('D', 'S', 'P'):
        ui.warn("Unknown push target '%s'\n" % resp)
        return 1

    args = []
    resp = resp.upper()
    if 'D' in resp: args.append("dev")
    if 'S' in resp: args.append("stage")
    if 'P' in resp: args.append(repo.topicProdBranch)

    opts = { 'nopull':False, 'nocommit':False, 'message':None }

  # If pushing to prod, get extra verification from the user
  nameSet = set()
  for name, path in ui.configitems("paths"):
    nameSet.add(name)
  if repo.topicProdBranch in args:
    if not repo.topicProdBranch in nameSet:
      raise util.Abort("Error: '%s' server path not configured in .hg/hgrc." % repo.topicProdBranch)
    res = ui.prompt("This will push to production. Okay to proceed?")
    if res.lower() != "y" and res.lower() != "yes":
      raise util.Abort("Ok.")
    if "stage" in nameSet and not "stage" in args:
      args = ["stage"] + list(args)
    if "dev" in nameSet and not "dev" in args:
      args = ["dev"] + list(args)

  # We'll use a special set of options for hg push commands
  pushOpts = copy.deepcopy(opts)
  pushOpts['new_branch'] = True  # allow pushing new branches

  # If no branch was specified, just share the current branch
  if len(args) < 1:
    if tryCommand(ui, "push --new-branch -b %s" % quoteBranch(topicBranch),
                  lambda:commands.push(ui, repo, branch=(topicBranch,), **pushOpts),
                  repo=repo):
      return 1
    ui.status("Done.\n")
    return 0

  commitStop = False # note if we get to that step

  # If pushing to prod, merge changes from this branch into the prod branch.
  alreadyMerged = [p.branch() for p in repo[None].parents()[0].children()]
  if repo.topicProdBranch in args and not repo.topicProdBranch in alreadyMerged:

    # Freshen with recent changes from prod
    freshenOpts = copy.deepcopy(opts)
    freshenOpts['terse'] = True # avoid printing "Done." at end
    if tfreshen(ui, repo, *args, **freshenOpts):
      return 1

    # Update to the prod
    if tryCommand(ui, "update %s" % quoteBranch(repo.topicProdBranch),
                  lambda:hg.update(repo, revsymbol(repo, repo.topicProdBranch))):
      return 1

    # Merge from the topic branch
    if doMerge(ui, repo, topicBranch):
      return 1

    # Stop if requested.
    if opts['nocommit']:
      ui.status("\nStopping before commit as requested.\n")
      commitStop = True
      return 0

    # Unlike a normal hg commit, if no text is specified we supply a reasonable default.
    text = opts.get('message')
    if text is None:
      text = "Merge %s to %s" % (topicBranch, repo.topicProdBranch)

    # Commit the merge.
    if tryCommand(ui, "commit", lambda:repo.commit(text) is None):
      return 1

    # And return to the original topic branch
    if repo.dirstate.branch() != topicBranch:
      if tryCommand(ui, "update %s" % quoteBranch(topicBranch), lambda:hg.update(repo, revsymbol(repo, topicBranch))):
        return 1

  # For prod, push to the central repo as well as the servers.
  if repo.topicProdBranch in args:
    try:
      if tryCommand(ui, "push --new-branch -b %s default" % repo.topicProdBranch,
                    lambda:commands.push(ui, repo, branch=(repo.topicProdBranch,), **pushOpts),
                    repo=repo) > 1:
        return 1
    except Exception, e:
      if "Not allowed to create multiple heads in the same branch" in ui.lastTryCommandOutput \
         or "push creates new remote head" in ui.lastTryCommandOutput \
         or "push creates new remote head" in str(e):
        print("Attempting to repair multiple heads.")
        if repo.dirstate.branch() != topicBranch:
          if tryCommand(ui, "update %s" % quoteBranch(topicBranch), lambda:hg.update(repo, revsymbol(repo, topicBranch))) > 1:
            return 1
        topicDir = os.path.dirname(__file__)
        repairScript = os.path.join(topicDir, "repair.py")
        subprocess.check_call([repairScript, repo.topicProdBranch, 'default'])
      else:
        raise
Esempio n. 35
0
 def push(self, dest=None, rev=None):
     self.invalidate_cache()
     commands.push(self.ui, self.repo, dest, rev=rev)
Esempio n. 36
0
    def internal_push_over_svnserve(self, subdir='', commit=True):
        repo_path = self.load_svndump('simple_branch.svndump')
        open(os.path.join(repo_path, 'conf', 'svnserve.conf'),
             'w').write('[general]\nanon-access=write\n[sasl]\n')
        self.port = random.randint(socket.IPPORT_USERRESERVED, 65535)
        self.host = socket.gethostname()

        # The `svnserve` binary appears to use the obsolete `gethostbyname(3)`
        # function, which always returns an IPv4 address, even on hosts that
        # support and expect IPv6. As a workaround, resolve the hostname
        # within the test harness with `getaddrinfo(3)` to ensure that the
        # client and server both use the same IPv4 or IPv6 address.
        try:
            addrinfo = socket.getaddrinfo(self.host, self.port)
        except socket.gaierror as e:
            # gethostname() can give a hostname that doesn't
            # resolve. Seems bad, but let's fall back to `localhost` in
            # that case and hope for the best.
            self.host = 'localhost'
            addrinfo = socket.getaddrinfo(self.host, self.port)
        # On macOS svn seems to have issues with IPv6 at least some of
        # the time, so try and bias towards IPv4. This works because
        # AF_INET is less than AF_INET6 on all platforms I've
        # checked. Hopefully any platform where that's not true will
        # be fine with IPv6 all the time. :)
        selected = sorted(addrinfo)[0]
        self.host = selected[4][0]

        # If we're connecting via IPv6 the need to put brackets around the
        # hostname in the URL.
        ipv6 = selected[0] == socket.AF_INET6

        # Ditch any interface information since that's not helpful in
        # a URL
        if ipv6 and ':' in self.host and '%' in self.host:
            self.host = self.host.rsplit('%', 1)[0]

        urlfmt = 'svn://[%s]:%d/%s' if ipv6 else 'svn://%s:%d/%s'

        args = [
            'svnserve', '--daemon', '--foreground',
            '--listen-port=%d' % self.port,
            '--listen-host=%s' % self.host,
            '--root=%s' % repo_path
        ]

        svnserve = subprocess.Popen(args,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)
        self.svnserve_pid = svnserve.pid
        try:
            time.sleep(2)
            import shutil
            shutil.rmtree(self.wc_path)
            commands.clone(self.ui(),
                           urlfmt % (self.host, self.port, subdir),
                           self.wc_path,
                           noupdate=True)

            repo = self.repo
            old_tip = revsymbol(repo, 'tip').node()
            expected_parent = revsymbol(repo, 'default').node()

            def file_callback(repo, memctx, path):
                if path == 'adding_file':
                    return compathacks.makememfilectx(repo,
                                                      memctx=memctx,
                                                      path=path,
                                                      data='foo',
                                                      islink=False,
                                                      isexec=False,
                                                      copied=False)
                raise IOError(errno.EINVAL, 'Invalid operation: ' + path)

            ctx = context.memctx(repo,
                                 parents=(revsymbol(repo, 'default').node(),
                                          node.nullid),
                                 text='automated test',
                                 files=['adding_file'],
                                 filectxfn=file_callback,
                                 user='******',
                                 date='2008-10-07 20:59:48 -0500',
                                 extra={
                                     'branch': 'default',
                                 })
            new_hash = repo.commitctx(ctx)
            if not commit:
                return  # some tests use this test as an extended setup.
            hg.update(repo, revsymbol(repo, 'tip').node())
            oldauthor = revsymbol(repo, 'tip').user()
            commands.push(repo.ui, repo)
            tip = revsymbol(self.repo, 'tip')
            self.assertNotEqual(oldauthor, tip.user())
            self.assertNotEqual(tip.node(), old_tip)
            self.assertEqual(tip.parents()[0].node(), expected_parent)
            self.assertEqual(tip['adding_file'].data(), 'foo')
            self.assertEqual(tip.branch(), 'default')
            # unintended behaviour:
            self.assertNotEqual('an_author', tip.user())
            self.assertEqual('(no author)', tip.user().rsplit('@', 1)[0])
        finally:
            if sys.version_info >= (2, 6):
                svnserve.kill()
            else:
                test_util.kill_process(svnserve)
Esempio n. 37
0
      else:
        raise

  # Now push to each server
  branchToPush = repo.topicProdBranch if repo.topicProdBranch in args else topicBranch
  for mergeTo in args:

    # Cannot merge to default, or to a topic branch
    if mergeTo in repo.topicIgnoreBranches and mergeTo not in ('dev', 'stage'):
      ui.warn("Cannot merge to '%s' branch.\n" % mergeTo)
      return 1

    # Push to the correct server
    if mergeTo in nameSet:
      if tryCommand(ui, "push --new-branch -b %s %s" % (branchToPush, mergeTo),
                    lambda:commands.push(ui, repo, branch=(branchToPush,), dest=mergeTo, **pushOpts),
                    repo=repo) > 1:   # 1 means nothing to push, which is ok
        return 1
    else:
      print("Note: No path for server '%s' is configured in .hg/hgrc." % mergeTo)

    # Record the push so we can display the right branch status later
    readTopicState(repo)
    if not topicBranch in topicState:
      topicState[topicBranch] = {}
    topicState[topicBranch][mergeTo] = repo[repo.dirstate.parents()[0]].hex()
    writeTopicState(repo)

  ui.status("Done.\n")

###############################################################################