def absolute(builder, co_dir, co_name, repo_url, rev=None, branch=None): """ Check out a multilevel repository from an absolute URL. <repo_url> must be of the form <vcs>+<url>, where <vcs> is one of the support version control systems (e.g., 'git', 'svn'). <rev> may be a revision (specified as a string). "HEAD" (or its equivalent) is assumed by default. <branch> may be a branch. "master" (or its equivalent) is assumed by default. The repository <repo_url> will be checked out into src/<co_dir>. The checkout will be identified by the label checkout:<co_name>/checked_out. """ vcs, base_url = split_vcs_url(repo_url) repo = Repository.from_url(vcs, base_url, revision=rev, branch=branch) # The version control handler wants to know the "leaf" separately # from the rest of the checkout path relative to src/ co_dir_dir, co_dir_leaf = os.path.split(co_dir) co_label = Label(utils.LabelType.Checkout, co_name, domain=builder.default_domain) checkout_from_repo(builder, co_label, repo, co_dir=co_dir_dir, co_leaf=co_dir_leaf)
def relative(builder, co_name, repo_relative=None, rev=None, branch=None): """ A simple, VCS-controlled, checkout. <rev> may be a revision (specified as a string). "HEAD" (or its equivalent) is assumed by default. <branch> may be a branch. "master" (or its equivalent) is assumed by default. If <repo_relative> is None then the repository <base_url>/<co_name> will be checked out into src/<co_name>, where <base_url> is the base URL as specified in .muddle/RootRepository (i.e., the base URL of the build description, as used in "muddle init"). For example:: <base_url>/<co_name> --> src/<co_name> If <repo_relative> is not None, then the repository <base_url>/<repo_relative> will be checked out instead:: <base_url>/<repo_relative> --> src/<co_name> """ base_repo = builder.build_desc_repo if repo_relative: repo_url = urljoin(base_repo.base_url, repo_relative) repo = Repository.from_url(base_repo.vcs, repo_url, revision=rev, branch=branch) else: repo = base_repo.copy_with_changes(co_name, revision=rev, branch=branch) co_label = Label(utils.LabelType.Checkout, co_name, domain=builder.default_domain) checkout_from_repo(builder, co_label, repo)
def absolute(builder, co_dir, co_name, repo_url, rev=None, branch=None): """ Check out a twolevel repository from an absolute URL. <repo_url> must be of the form <vcs>+<url>, where <vcs> is one of the support version control systems (e.g., 'git', 'svn'). <rev> may be a revision (specified as a string). "HEAD" (or its equivalent) is assumed by default. <branch> may be a branch. "master" (or its equivalent) is assumed by default. The repository <repo_url>/<co_name> will be checked out into src/<co_dir>/<co_name>. """ co_path = os.path.join(co_dir, co_name) vcs, base_url = split_vcs_url(repo_url) repo = Repository.from_url(vcs, base_url, revision=rev, branch=branch) co_label = Label(utils.LabelType.Checkout, co_name, domain=builder.default_domain) checkout_from_repo(builder, co_label, repo, co_dir=co_dir)
def check_push_pull_permissions(): class DummyBuilder(object): def checkout_path(self, anything): return '' dummy_builder = DummyBuilder() dummy_builder.db = Database(',') banner('CHECK PUSH/PULL PERMISSIONS') fred = Label.from_string('checkout:fred/*') vcs = VersionControlHandler(vcs=None) repo = Repository.from_url('git', 'http://example.com/Fred.git', pull=False) # We can't use version_control.py::checkout_from_repo() directly, because # it already checks the "pull" value for us... co_data = CheckoutData(vcs, repo, None, 'fred') dummy_builder.db.set_checkout_data(fred, co_data) check_exception('Test checkout_from_repo with %r' % repo, checkout_from_repo, (None, fred, repo), exception=MuddleBug, startswith='Checkout checkout:fred/* cannot use') check_exception('Test checkout from repo %r' % repo, vcs.checkout, (dummy_builder, fred), endswith='does not allow "pull"') check_exception('Test pull from repo %r' % repo, vcs.pull, (dummy_builder, fred), endswith='does not allow "pull"') check_exception('Test merge from repo %r' % repo, vcs.merge, (dummy_builder, fred), endswith='does not allow "pull"') co_data.repo = Repository.from_url('git', 'http://example.com/Fred.git', push=False) check_exception('Test push to repo %r' % repo, vcs.push, (dummy_builder, fred), endswith='does not allow "push"')
def vcs_pull_directory(url): """ Pull the current directory from the repository indicated by the URL Looks at the first few characters of the URL to determine the VCS to use - so, e.g., "bzr" for "bzr+ssh://whatever". Raises KeyError if the scheme is not one for which we have a registered handler. """ vcs_instance, plain_url = get_vcs_instance_from_string(url) repo = Repository.from_url(vcs_instance.short_name, plain_url) vcs_instance.pull(repo, {})
def check_push_pull_permissions(): class DummyBuilder(object): def checkout_path(self, anything): return '' dummy_builder = DummyBuilder() dummy_builder.db = Database(',') banner('CHECK PUSH/PULL PERMISSIONS') fred = Label.from_string('checkout:fred/*') vcs = VersionControlHandler(vcs=None) repo = Repository.from_url('git', 'http://example.com/Fred.git', pull=False) # We can't use version_control.py::checkout_from_repo() directly, because # it already checks the "pull" value for us... co_data = CheckoutData(vcs, repo, None, 'fred') dummy_builder.db.set_checkout_data(fred, co_data) check_exception('Test checkout_from_repo with %r'%repo, checkout_from_repo, (None, fred, repo), exception=MuddleBug, startswith='Checkout checkout:fred/* cannot use') check_exception('Test checkout from repo %r'%repo, vcs.checkout, (dummy_builder, fred), endswith='does not allow "pull"') check_exception('Test pull from repo %r'%repo, vcs.pull, (dummy_builder, fred), endswith='does not allow "pull"') check_exception('Test merge from repo %r'%repo, vcs.merge, (dummy_builder, fred), endswith='does not allow "pull"') co_data.repo = Repository.from_url('git', 'http://example.com/Fred.git', push=False) check_exception('Test push to repo %r'%repo, vcs.push, (dummy_builder, fred), endswith='does not allow "push"')
def vcs_get_directory(url, directory=None): """ Retrieve (clone) the directory identified by the URL, via its VCS. If 'directory' is given, then clones to the named directory. Looks at the first few characters of the URL to determine the VCS to use - so, e.g., "bzr" for "bzr+ssh://whatever". Raises KeyError if the scheme is not one for which we have a registered handler. """ vcs_instance, plain_url = get_vcs_instance_from_string(url) repo = Repository.from_url(vcs_instance.short_name, plain_url) return vcs_instance.checkout(repo, directory, {})
def absolute(builder, co_name, repo_url, rev=None, branch=None): """ Check out a repository from an absolute URL. <repo_url> must be of the form <vcs>+<url>, where <vcs> is one of the support version control systems (e.g., 'git', 'svn'). <rev> may be a revision (specified as a string). "HEAD" (or its equivalent) is assumed by default. <branch> may be a branch. "master" (or its equivalent) is assumed by default. The repository <repo_url>/<co_name> will be checked out into src/<co_name>. """ vcs, base_url = split_vcs_url(repo_url) repo = Repository.from_url(vcs, base_url, revision=rev, branch=branch) co_label = Label(utils.LabelType.Checkout, co_name, domain=builder.default_domain) checkout_from_repo(builder, co_label, repo)
def test_builds_ok_upstream_3(root): with NewCountedDirectory('builds_ok_upstream_3') as d: banner( 'CHECK REPOSITORIES OUT (OK UPSTREAM 3) subdomain has extra upstream names' ) muddle([ 'init', 'git+file://{repo}/main'.format(repo=root.join('repo')), 'builds_ok_upstream_3/01.py' ]) text = captured_muddle(['query', 'upstream-repos']) check_text_endswith( text, """\ > Upstream repositories .. Repository('git', 'file://{root_dir}/repo/main', 'repo1') used by checkout:co_repo1/*, checkout:(subdomain_ok_upstream_3)co_repo1/* Repository('git', 'file://{root_dir}/repo/main', 'repo1.1') rhubarb, wombat Repository('git', 'file://{root_dir}/repo/main', 'repo1.2', push=False) insignificance, manhattan, platypus, wombat Repository('git', 'file://{root_dir}/repo/main', 'repo1.3', pull=False) platypus, rhubarb Repository('git', 'http://example.com', 'repo99') Repository('git', 'http://example.com', 'repo99-upstream') abacus """.format(root_dir=root.where))
def relative(builder, co_dir, co_name, repo_relative = None, rev = None, branch = None): """ A multilevel checkout, with checkout name unrelated to checkout directory. Sometimes it is necessary to cope with checkouts that either: a. are more than two directories below src/, or b. have a checkout name that is not the same as the "leaf" directory in their path Both of these can happen when trying to represent an Android build, for instance. Thus:: multilevel.relative(builder, co_dir='this/is/here', co_name='checkout1') will look for the repository <base_url>/this/is/here and check it out into src/this/is/here, but give it label checkout:checkout1/checked_out. (<base_url> is the base URL as specified in .muddle/RootRepository (i.e., the base URL of the build description, as used in "muddle init"). For the moment, <repo_relative> is ignored. """ base_repo = builder.build_desc_repo # urljoin doesn't work well with the sort of path fragment we tend to have repo_url = posixpath.join(base_repo.base_url, co_dir) repo = Repository.from_url(base_repo.vcs, repo_url, revision=rev, branch=branch) # The version control handler wants to know the "leaf" separately # from the rest of the checkout path relative to src/ co_dir_dir, co_dir_leaf = os.path.split(co_dir) co_label = Label(utils.LabelType.Checkout, co_name, domain=builder.default_domain) checkout_from_repo(builder, co_label, repo, co_dir=co_dir_dir, co_leaf=co_dir_leaf)
def test_using_upstreams(root_dir): err, text = captured_muddle2(['query', 'upstream-repos', 'co_label1']) check_text( text, "\nThere is no checkout data (repository) registered for label checkout:co_label1/checked_out\n" ) assert err == 1 text = captured_muddle(['query', 'upstream-repos', 'co_repo1']) check_text( text, """\ Repository('git', 'file://{root_dir}/repo/main', 'repo1') used by checkout:co_repo1/checked_out Repository('git', 'file://{root_dir}/repo/main', 'repo1.1') rhubarb, wombat Repository('git', 'file://{root_dir}/repo/main', 'repo1.2', push=False) insignificance, wombat Repository('git', 'file://{root_dir}/repo/main', 'repo1.3', pull=False) platypus, rhubarb """.format(root_dir=root_dir)) err, text = captured_muddle2([ 'pull-upstream', 'package:package1', 'builds', '-u', 'rhubarb', 'wombat' ]) assert err == 1 check_text( text, """\ Nowhere to pull checkout:builds/checked_out from Pulling checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.1 (rhubarb, wombat) ++ pushd to {root_dir}/build/src/co_repo1 > git remote add rhubarb file://{root_dir}/repo/main/repo1.1 > git fetch rhubarb From file://{root_dir}/repo/main/repo1.1 * [new branch] master -> rhubarb/master > git merge --ff-only remotes/rhubarb/master Already up-to-date. Pulling checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.2 (wombat) ++ pushd to {root_dir}/build/src/co_repo1 > git remote add wombat file://{root_dir}/repo/main/repo1.2 > git fetch wombat From file://{root_dir}/repo/main/repo1.2 * [new branch] master -> wombat/master > git merge --ff-only remotes/wombat/master Already up-to-date. Pulling checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.3 (rhubarb) Failure pulling checkout:co_repo1/checked_out in src/co_repo1: file://{root_dir}/repo/main/repo1.3 does not allow "pull" """.format(root_dir=root_dir)) err, text = captured_muddle2([ 'push-upstream', 'package:package1', 'builds', '-u', 'rhubarb', 'wombat' ]) assert err == 1 check_text( text, """\ Nowhere to push checkout:builds/checked_out to Pushing checkout:co_repo1/checked_out to file://{root_dir}/repo/main/repo1.1 (rhubarb, wombat) ++ pushd to {root_dir}/build/src/co_repo1 > git push rhubarb HEAD Everything up-to-date Pushing checkout:co_repo1/checked_out to file://{root_dir}/repo/main/repo1.2 (wombat) Failure pushing checkout:co_repo1/checked_out in src/co_repo1: file://{root_dir}/repo/main/repo1.2 does not allow "push" """.format(root_dir=root_dir)) err, text = captured_muddle2([ '-n', 'pull-upstream', 'package:package1', 'builds', '-u', 'rhubarb', 'wombat' ]) assert err == 0 check_text( text, """\ Asked to pull-upstream: checkout:builds/checked_out checkout:co_repo1/checked_out for: rhubarb, wombat Nowhere to pull checkout:builds/checked_out from Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.1 (rhubarb, wombat) Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.2 (wombat) Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.3 (rhubarb) """.format(root_dir=root_dir)) err, text = captured_muddle2([ '-n', 'pull-upstream', 'package:package1', 'builds', '-u', 'rhubarb', 'wombat' ]) assert err == 0 check_text( text, """\ Asked to pull-upstream: checkout:builds/checked_out checkout:co_repo1/checked_out for: rhubarb, wombat Nowhere to pull checkout:builds/checked_out from Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.1 (rhubarb, wombat) Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.2 (wombat) Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.3 (rhubarb) """.format(root_dir=root_dir)) with Directory('src'): with Directory('co_repo1'): # None of that should have changed where *origin* points text = run1('git remote show origin', show_output=True) check_text( text, """\ * remote origin Fetch URL: file://{root_dir}/repo/main/repo1 Push URL: file://{root_dir}/repo/main/repo1 HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) """.format(root_dir=root_dir))
def test_using_upstreams(root_dir): err, text = captured_muddle2(['query', 'upstream-repos', 'co_label1']) check_text( text, "\nThere is no checkout data (repository) registered for label checkout:co_label1/checked_out\n" ) assert err == 1 text = captured_muddle(['query', 'upstream-repos', 'co_repo1']) check_text( text, """\ Repository('git', 'file://{root_dir}/repo/main', 'repo1') used by checkout:co_repo1/checked_out Repository('git', 'file://{root_dir}/repo/main', 'repo1.1') rhubarb Repository('git', 'file://{root_dir}/repo/main', 'repo1.2', push=False) wombat Repository('git', 'file://{root_dir}/repo/main', 'repo1.3', pull=False) platypus """.format(root_dir=root_dir)) err, text = captured_muddle2( ['pull-upstream', 'package:package1', 'builds', '-u', 'platypus']) assert err == 1 check_text( text, """\ Nowhere to pull checkout:builds/checked_out from Pulling checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.3 (platypus) Failure pulling checkout:co_repo1/checked_out in src/co_repo1: file://{root_dir}/repo/main/repo1.3 does not allow "pull" """.format(root_dir=root_dir)) err, text = captured_muddle2([ 'push-upstream', 'package:package1', 'builds', '-u', 'wombat', 'wombat' ]) assert err == 1 check_text( text, """\ Nowhere to push checkout:builds/checked_out to Pushing checkout:co_repo1/checked_out to file://{root_dir}/repo/main/repo1.2 (wombat) Failure pushing checkout:co_repo1/checked_out in src/co_repo1: file://{root_dir}/repo/main/repo1.2 does not allow "push" """.format(root_dir=root_dir)) err, text = captured_muddle2([ '-n', 'pull-upstream', 'package:package1', 'builds', '-u', 'rhubarb', 'wombat' ]) assert err == 0 check_text( text, """\ Asked to pull-upstream: checkout:builds/checked_out checkout:co_repo1/checked_out for: rhubarb, wombat Nowhere to pull checkout:builds/checked_out from Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.1 (rhubarb) Would pull checkout:co_repo1/checked_out from file://{root_dir}/repo/main/repo1.2 (wombat) """.format(root_dir=root_dir)) with Directory('src'): with Directory('co_repo1'): # None of that should have changed where *origin* points text = get_stdout('git remote show origin') check_text( text, """\ * remote origin Fetch URL: file://{root_dir}/repo/main/repo1 Push URL: file://{root_dir}/repo/main/repo1 HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) """.format(root_dir=root_dir))