def tar_pack(label, co_dir, co_leaf, repo, output_dir, manifest_filename): if label.domain: domparts = Label.split_domains(label.domain) name = '%s-%s'%('_'.join(domparts), label.name) else: name = label.name tar_filename = '%s.tgz'%name tar_path = os.path.join(output_dir, tar_filename) parent_dir = deduce_checkout_parent_dir(co_dir) # *Should* check that neither of the requested revision ids # are above the id of the checkout we have to hand? cmd = 'tar -C %s -zcf %s %s'%(parent_dir, tar_path, co_leaf) print '..',cmd rv = subprocess.call(cmd, shell=True) if rv: raise LocalError('tar -zcf returned %d'%rv) with open(manifest_filename, 'a') as fd: # Lazily, just write this out by hand # It should be much more information than we need, but still fd.write('[TAR %s]\n' 'co_label=%s\n' 'co_dir=%s\n' 'co_leaf=%s\n' 'patch=%s\n'%(name, label, co_dir, co_leaf, tar_filename))
def do_deps(gbuilder, goal): """ Main dependency walker. Recurses depth-first. """ # deps := `muddle depend user-short goal` ! #print 'Would do %s'%goal label = Label.from_string(goal) rules = gbuilder.ruleset.rules_for_target(label) goalnode = Node.get(goal) assert goalnode is not None for rule in rules: target = rule.target builder = None if rule.action: builder = rule.action.__class__.__name__ # AptGetBuilders aren't very interesting, condense them. if builder == 'AptGetBuilder': goalnode.displayname = '%s{%s}\\n(AptGetBuilder)' % (rule.action.name, rule.action.role) goalnode.extras = 'shape=oval' goalnode.isAptGet = True continue rawdeps = [] for label in rule.deps: if not label.system: rawdeps.append(label) rawdeps.sort() for dep in rawdeps: newnode = False try: depnode = Node.get(dep) except KeyError: depnode = Node(dep) newnode = True label = None if builder: label = '[label="%s"]'%builder try: existEdge = Edge.get(depnode,goalnode) except KeyError: Edge(depnode, goalnode, label) if newnode: do_deps(gbuilder, str(dep))
def bzr_send(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename): if label.domain: domparts = Label.split_domains(label.domain) name = '%s-%s'%('_'.join(domparts), label.name) else: name = label.name if BZR_DO_IT_PROPERLY: output_filename = '%s.bzr_send'%name else: output_filename = '%s.diff'%name output_path = os.path.join(output_dir, output_filename) checkout_dir = deduce_checkout_dir(co_dir, co_leaf) # *Should* check that neither of the requested revision numbers # are above the revno of the checkout we have to hand? Anyway, # probably the checks in Bazaar.revision_to_checkout() are what # we would want to be doing... if BZR_DO_IT_PROPERLY: cmd = 'cd %s; bzr send --output=%s --revision=%s..%s -v'%(checkout_dir, output_path, rev1, rev2) print '..',cmd rv = subprocess.call(cmd, shell=True) if rv != 0: raise LocalError('bzr send for %s returned %d'%(label,rv)) else: cmd = 'cd %s; bzr diff -p1 -r%s..%s -v > %s'%(checkout_dir, rev1, rev2, output_path) print '..',cmd rv = subprocess.call(cmd, shell=True) if rv != 1: # for some reason raise LocalError('bzr send for %s returned %d'%(name,rv)) with open(manifest_filename, 'a') as fd: # Lazily, just write this out by hand fd.write('[BZR %s]\n' 'co_label=%s\n' 'co_dir=%s\n' 'co_leaf=%s\n' 'patch=%s\n' 'old_revision=%s\n' 'new_revision=%s\n'%(name, label, co_dir, co_leaf, output_filename, rev1, rev2))
def git_format_patch(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename): if label.domain: domparts = Label.split_domains(label.domain) name = '%s-%s'%('_'.join(domparts), label.name) else: name = label.name output_directory = '%s.git_patch'%name output_path = os.path.join(output_dir, output_directory) checkout_dir = deduce_checkout_dir(co_dir, co_leaf) # *Should* check that neither of the requested revision ids # are above the id of the checkout we have to hand? if rev1 is None: raise LocalError('Cannot do git-format patch: rev1 is None') if rev2 is None: raise LocalError('Cannot do git-format patch: rev2 is None') cmd = 'cd %s; git format-patch -o %s' \ ' %s..%s'%(checkout_dir, output_path, rev1, rev2) print '..',cmd rv = subprocess.call(cmd, shell=True) if rv: raise LocalError('git format-patch returned %d'%rv) with open(manifest_filename, 'a') as fd: # Lazily, just write this out by hand fd.write('[GIT %s]\n' 'co_label=%s\n' 'co_dir=%s\n' 'co_leaf=%s\n' 'patch=%s\n' 'old_revision=%s\n' 'new_revision=%s\n'%(name, label, co_dir, co_leaf, output_path, rev1, rev2))
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 svn_diff(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename): if label.domain: domparts = Label.split_domains(label.domain) name = '%s-%s'%('_'.join(domparts), label.name) else: name = label.name output_filename = '%s.svn_diff'%name output_path = os.path.join(output_dir, output_filename) checkout_dir = deduce_checkout_dir(co_dir, co_leaf) # *Should* check that neither of the requested revision numbers # are above the revno of the checkout we have to hand? Anyway, # probably the checks in Bazaar.revision_to_checkout() are what # we would want to be doing... # 'svn diff' is probably the best we can do cmd = 'cd %s; svn diff -r %s:%s > %s'%(checkout_dir, rev1, rev2, output_path) print '..',cmd rv = subprocess.call(cmd, shell=True) if rv: raise LocalError('svn diff returned %d'%rv) with open(manifest_filename, 'a') as fd: # Lazily, just write this out by hand fd.write('[SVN %s]\n' 'co_label=%s\n' 'co_dir=%s\n' 'co_leaf=%s\n' 'patch=%s\n' 'old_revision=%s\n' 'new_revision=%s\n'%(name, label, co_dir, co_leaf, output_filename, rev1, rev2))
def guess_cmd_in_build(builder, current_dir): """Returns a tuple (command_name, args) """ # Where are we? where = builder.find_location_in_tree(current_dir) if where is None: raise utils.GiveUp("Can't decide what to do, can't seem to" " determine where you are in the build tree") what, label, domain = where args = [] if what == DirType.Root: # We're at the very top of the build tree # # As such, our default is to build labels: command_name = "buildlabel" # and the labels to build are the default deployments args = map(str, builder.default_deployment_labels) # and the default roles for role in builder.default_roles: label = Label(LabelType.Package, '*', role, LabelTag.PostInstalled) args.append(str(label)) elif what == DirType.DomainRoot: domains = [] if domain is None: subdirs = os.listdir(current_dir) # Make a quick plausibility check for dir in subdirs: if os.path.isdir(os.path.join(current_dir, dir, '.muddle')): domains.append(dir) else: domains.append(domain) # We're in domains/<somewhere>, so build everything specific # to (just) this subdomain command_name = "buildlabel" # Choose all the packages from this domain that are needed by # our build tree. Also, all the deployments that it contributes # to our build tree. It is possible we might end up "over building" # if any of those are not implied by the top-level build defaults, # but that would be somewhate more complex to determine. for name in domains: args.append('deployment:({domain})*/deployed'.format(domain=name)) args.append('package:({domain})*{{*}}/postinstalled'.format(domain=name)) elif what == DirType.Deployed: # We're in a deploy/ directory, so redeploying sounds sensible # The redeploy command knows to "look around" and decide *what* # needs redeploying command_name = "redeploy" if label: # Given a specific deployment, choose it args.append(str(label)) elif what == DirType.Object or what == DirType.Install: # We're in obj/ or install/, so rebuilding is what we want to do # The rebuild command knows to "look around" and decide *what* # needs rebuilding command_name = "rebuild" elif what == DirType.Checkout: # We're in src/, so we want to build, not rebuild # The build command knows to "look around" and decide *what* # needs building command_name = "build" else: raise utils.GiveUp("Don't know what to do in this location: %s"%what) return command_name, args
def label_domain_sort(): """Test sorting labels with domain names in them. """ # Yes, apparently these are all legitimate label names # The domain names are the same as those used in the docstring for # utils.sort_domains() labels = [ Label.from_string('checkout:(a)fred/*'), Label.from_string('checkout:(+(1))fred/*'), Label.from_string('checkout:(-(2))fred/*'), Label.from_string('checkout:(a(b(c2)))fred/*'), Label.from_string('checkout:(a(b(c1)))fred/*'), Label.from_string('checkout:(+(1(+2(+4(+4)))))fred/*'), Label.from_string('checkout:(b(b))fred/*'), Label.from_string('checkout:(b)fred/*'), Label.from_string('checkout:(b(a))fred/*'), Label.from_string('checkout:(a(a))fred/*'), Label.from_string('checkout:(+(1(+2)))fred/*'), Label.from_string('checkout:(+(1(+2(+4))))fred/*'), Label.from_string('checkout:(+(1(+3)))fred/*'), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:(+(1))fred/*" " checkout:(+(1(+2)))fred/*" " checkout:(+(1(+2(+4))))fred/*" " checkout:(+(1(+2(+4(+4)))))fred/*" " checkout:(+(1(+3)))fred/*" " checkout:(-(2))fred/*" " checkout:(a)fred/*" " checkout:(a(a))fred/*" " checkout:(a(b(c1)))fred/*" " checkout:(a(b(c2)))fred/*" " checkout:(b)fred/*" " checkout:(b(a))fred/*" " checkout:(b(b))fred/*") # A specific test, which we originally got wrong labels = [ Label.from_string('checkout:(sub1)builds/checked_out'), Label.from_string('checkout:(sub1(sub4))builds/checked_out'), Label.from_string('checkout:(sub1(sub5))builds/checked_out'), Label.from_string('checkout:(sub2)builds/checked_out'), Label.from_string('checkout:(sub1(sub4))co0/checked_out'), Label.from_string('checkout:(sub1(sub5))co0/checked_out'), Label.from_string('checkout:(sub2(sub3))builds/checked_out'), Label.from_string('checkout:(sub2(sub3))co0/checked_out'), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels #print 'xxx' #for label in sorted_labels: # print ' ', str(label) #print 'xxx' # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:(sub1)builds/checked_out" " checkout:(sub1(sub4))builds/checked_out" " checkout:(sub1(sub4))co0/checked_out" " checkout:(sub1(sub5))builds/checked_out" " checkout:(sub1(sub5))co0/checked_out" " checkout:(sub2)builds/checked_out" " checkout:(sub2(sub3))builds/checked_out" " checkout:(sub2(sub3))co0/checked_out") # Another originally erroneous case l1 = Label.from_string("checkout:(subdomain2(subdomain3))main_co/checked_out") l2 = Label.from_string("checkout:first_co/checked_out") print print 'xx', l1 print 'xx', l2 print 'xx l2 < l1', l2 < l1 assert l2 < l1 labels = [ Label.from_string("checkout:main_co/checked_out"), Label.from_string("checkout:(subdomain1)first_co/checked_out"), Label.from_string("checkout:(subdomain1)main_co/checked_out"), Label.from_string("checkout:(subdomain1)second_co/checked_out"), Label.from_string("checkout:(subdomain1(subdomain3))first_co/checked_out"), Label.from_string("checkout:(subdomain1(subdomain3))main_co/checked_out"), Label.from_string("checkout:(subdomain1(subdomain3))second_co/checked_out"), Label.from_string("checkout:(subdomain2)first_co/checked_out"), Label.from_string("checkout:(subdomain2)main_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain3))main_co/checked_out"), Label.from_string("checkout:first_co/checked_out"), Label.from_string("checkout:second_co/checked_out"), Label.from_string("checkout:(subdomain2)second_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain3))first_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain3))second_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain4))first_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain4))main_co/checked_out"), Label.from_string("checkout:(subdomain2(subdomain4))second_co/checked_out"), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:first_co/checked_out" " checkout:main_co/checked_out" " checkout:second_co/checked_out" " checkout:(subdomain1)first_co/checked_out" " checkout:(subdomain1)main_co/checked_out" " checkout:(subdomain1)second_co/checked_out" " checkout:(subdomain1(subdomain3))first_co/checked_out" " checkout:(subdomain1(subdomain3))main_co/checked_out" " checkout:(subdomain1(subdomain3))second_co/checked_out" " checkout:(subdomain2)first_co/checked_out" " checkout:(subdomain2)main_co/checked_out" " checkout:(subdomain2)second_co/checked_out" " checkout:(subdomain2(subdomain3))first_co/checked_out" " checkout:(subdomain2(subdomain3))main_co/checked_out" " checkout:(subdomain2(subdomain3))second_co/checked_out" " checkout:(subdomain2(subdomain4))first_co/checked_out" " checkout:(subdomain2(subdomain4))main_co/checked_out" " checkout:(subdomain2(subdomain4))second_co/checked_out" )
def copy_from_role_install(builder, name, role, rel, dest, recursive=True, failOnAbsentSource=False, copyExactly=True, domain=None, usingRSync=False, obeyInstructions=True): """ Add a requirement to copy from the given role's install to the named deployment. 'name' is the name of the collecting deployment, as created by:: deploy(builder, name) which is remembered as a rule whose target is ``deployment:<name>/deployed``, where <name> is the 'name' given. 'role' is the role to copy from. Copying will be based from 'rel' within the role's ``install``, to 'dest' within the deployment. The label ``package:(<domain>)*{<role>}/postinstalled`` will be added as a dependency of the collecting deployment rule. An AssemblyDescriptor will be created to copy from 'rel' in the install directory of the label ``package:*{<role>}/postinstalled``, to 'dest' within the deployment directory of 'name', and added to the rule's actions. So, for instance:: copy_from_role_install(builder,'fred','data','public','data/public', True, False, True) might copy (recursively) from:: install/data/public to:: deploy/fred/data/public 'rel' may be the empty string ('') to copy all files in the install directory. - If 'recursive' is true, then copying is recursive, otherwise it is not. - If 'failOnAbsentSource' is true, then copying will fail if the source does not exist. - If 'copyExactly' is true, then symbolic links will be copied as such, otherwise the linked file will be copied. - If 'usingRSync' is true, copy with rsync - substantially faster than cp, if you have rsync. Not very functional if you don't :-) - If 'obeyInstructions' is False, don't obey any applicable instructions. """ rule = deployment.deployment_rule_from_name(builder, name) dep_label = Label(utils.LabelType.Package, "*", role, utils.LabelTag.PostInstalled, domain=domain) asm = AssemblyDescriptor(dep_label, rel, dest, recursive=recursive, failOnAbsentSource=failOnAbsentSource, copyExactly=copyExactly, usingRSync=usingRSync, obeyInstructions=obeyInstructions) rule.add(dep_label) rule.action.add_assembly(asm)
def depend_unit_test(): """ Some fairly simple tests for the dependency solver. """ l1 = Label(utils.LabelType.Checkout, "co_1", "role_1", utils.LabelTag.CheckedOut) l2 = Label(utils.LabelType.Checkout, "co_1", "role_1", utils.LabelTag.Pulled) l3 = Label(utils.LabelType.Package, "pkg_1", "role_1", utils.LabelTag.PreConfig) l4 = Label(utils.LabelType.Deployment, "dep_1", "role_2", utils.LabelTag.Built) # Check label_from_string .. lx = Label.from_string("foo:bar{baz}/wombat[T]") lx_a = Label("foo", "bar", "baz", "wombat") assert lx == lx_a assert lx.transient assert not lx.system lx = Label.from_string("foo:bar/wombat[T]") lx_a = Label("foo", "bar", None, "wombat") assert lx == lx_a assert lx.transient assert not lx.system lx = Label.from_string("*:bar/wombat") assert (lx is not None) lx_a = Label("*", "bar", None, "wombat") assert lx == lx_a assert not lx.transient assert not lx.system lx = Label.from_string("*:wombat/*") assert lx is not None lx_a = Label("*", "wombat", None, "*") assert lx == lx_a assert not lx.transient assert not lx.system lx = Label.from_string(l1.__str__()) assert lx is not None assert lx == l1 lx = Label.from_string(l2.__str__()) assert lx is not None assert lx == l2 lx = Label.from_string(l3.__str__()) assert lx is not None assert lx == l3 lx = Label.from_string(l4.__str__()) assert lx is not None assert lx == l4 # Let's check that label matching works the way we think it does .. la1 = Label(type='*', name=l1.name, domain=l1.domain, role=l1.role, tag=l1.tag) la2 = Label(type=l1.type, name='*', domain=l1.domain, role=l1.role, tag=l1.tag) la3 = Label(type=l1.type, name='*', domain=l1.domain, role='*', tag=l1.tag) la4 = l1.copy_with_tag('*') assert l1.match(l1) == 0 assert l2.match(l1) is None assert la1.match(l1) == -1 assert l1.match(la1) == -1 assert (l2.match(la4)) == -1 assert l1.match(la3) == -2 r1 = depend.Rule(l1, pkg.NoAction()) r2 = depend.Rule(l2, pkg.NoAction()) r2.add(l1) r3 = depend.Rule(l3, pkg.NoAction()) r4 = depend.Rule(l4, pkg.NoAction()) r3.add(l2) r4.add(l3); r4.add(l2) rs = depend.RuleSet() rs.add(r1) rs.add(r2) rs.add(r3) rs.add(r4) assert str(rs).strip() == """\ ----- checkout:co_1{role_1}/checked_out <-NoAction-- [ ] checkout:co_1{role_1}/pulled <-NoAction-- [ checkout:co_1{role_1}/checked_out ] deployment:dep_1{role_2}/built <-NoAction-- [ checkout:co_1{role_1}/pulled, package:pkg_1{role_1}/preconfig ] package:pkg_1{role_1}/preconfig <-NoAction-- [ checkout:co_1{role_1}/pulled ] -----""" r3_required_for = depend.needed_to_build(rs, l3) assert depend.rule_list_to_string(r3_required_for) == "[ checkout:co_1{role_1}/checked_out <-NoAction-- [ ], checkout:co_1{role_1}/pulled <-NoAction-- [ checkout:co_1{role_1}/checked_out ], package:pkg_1{role_1}/preconfig <-NoAction-- [ checkout:co_1{role_1}/pulled ], ]" r2_required_by = depend.required_by(rs, l2) assert depend.rule_list_to_string(r2_required_by) == "[ checkout:co_1{role_1}/pulled, deployment:dep_1{role_2}/built, package:pkg_1{role_1}/preconfig, ]"
def describe_to(builder): role = 'omap' roles = ['omap'] builder.add_default_role(role) # filedep.deploy(builder, target_dir, name, roles) # # Register a file deployment. # # The deployment will take the roles specified in the role list, and build # them into a deployment at deploy/[name]. # # The deployment should eventually be located at target_dir. filedep.deploy(builder, '/', 'omap', roles) # Both Linux and Busybox share some environment we'd like to specify # only once. The mechanism for doing this is a little bit cunning label = Label.from_string('package:*{omap}/*') # i.e., all our packages # We can retrieve the "environment" (technically, an environment Store) # that will be used for that label - this will create one if it doesn't # exist yet env = builder.get_environment_for(label) # And adding values to that is simple env.set("MUDDLE_CROSS_COMPILE", "/opt/codesourcery/arm-2008q3/bin/arm-none-linux-gnueabi-") env.set("MUDDLE_ARCH", "arm") # There's a variety of things we need on (this, the host) system # in order to build - I hope I've got this right (difficult to tell # as I already have some stuff installed on *my* development system) aptget.simple(builder, 'development_packages', role, ['zlib1g-dev', 'uboot-mkimage']) # According to http://omappedia.org/wiki/LinuxOMAP_Kernel_Project, we get # our OMAP kernel from: muddled.checkouts.simple.absolute( builder, 'omap_kernel', 'git+git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git' ) # Once we've got one worked out, we'll also want to retrieve a default # kernel configuration (we don't, eventually, want to make the developer # have to work that out every time!) # We'll aim to make that with an out-of-tree makefile # We could make a tailored subclass of muddled.pkgs.linux_kernel, and use # that to build our kernel. I may still do that once I've figured out how # it is different (one notable change is we're building uImage instead of # zImage). For now, it's probably easier to have a Makefile.muddle make.medium( builder, name="omap_kernel", # package name roles=roles, checkout="helpers", deps=[], makefileName=os.path.join("omap_kernel", "Makefile.muddle")) muddled.pkg.package_depends_on_checkout( builder.ruleset, "omap_kernel", # this package role, # in this role "omap_kernel") # depends on this checkout # On top of that, we want to build busybox # # According to the busybox website, we can retrieve sources via git: # # To grab a copy of the BusyBox repository using anonymous git access:: # # git clone git://busybox.net/busybox.git # # Once you have the repository, stable branches can be checked out by # doing:: # # git checkout remotes/origin/1_NN_stable # # Once you've checked out a copy of the source tree, you can update your # source tree at any time so it is in sync with the latest and greatest by # entering your BusyBox directory and running the command:: # # git pull # So, for the moment, at least, let's go with the latest from source # control (when we're finalising this, we're maybe better identifying # a particular release to stick to) muddled.checkouts.simple.absolute(builder, 'busybox', 'git+git://busybox.net/busybox.git') # We'll aim to make that with an out-of-tree makefile # # 'deps' is a list of package names, which our make depends on. # # Specifically, for each <name> in 'deps', and for each <role> in 'roles', # we will depend on "package:<name>{<role>}/postinstalled" make.medium( builder, name="busybox", # package name roles=roles, checkout="helpers", deps=['omap_kernel'], makefileName=os.path.join("busybox", "Makefile.muddle")) # And we also depend on having actually checked out busybox muddled.pkg.package_depends_on_checkout( builder.ruleset, "busybox", # this package role, # in this role "busybox", # depends on this checkout None) # Can we use the same bootloader and such that we already had for the # android build? # The bootloader and related items, which go into the FAT32 partition on # the flash card, are retrieved from the net (eventually, I hope we'll be # building u-boot, but for now the binary should do) muddled.checkouts.simple.absolute( builder, 'MLO', 'wget+http://free-electrons.com/pub/demos/beagleboard/android/MLO') muddled.checkouts.simple.absolute( builder, 'u-boot', 'wget+http://free-electrons.com/pub/demos/beagleboard/android/u-boot.bin' ) # We need some way of getting them installed - let's foreshadow the day when # we actually want to build u-boot ourselves, and pretend make.medium( builder, name="u-boot", # package name roles=roles, checkout="helpers", deps=[], makefileName=os.path.join("u-boot", "Makefile.muddle")) muddled.pkg.package_depends_on_checkout( builder.ruleset, "u-boot", # this package role, # in this role "u-boot", # depends on this checkout None) # Oh, and this one as well... rule = muddled.depend.depend_one( None, Label.from_string('package:u-boot{%s}/built' % role), Label.from_string('checkout:MLO/checked_out')) builder.ruleset.add(rule) # And, of course, we need (the rest of) our Linux filesystem muddled.checkouts.simple.absolute( builder, 'rootfs', 'bzr+ssh://[email protected]//opt/kynesim/projects/052/rootfs' ) make.simple(builder, 'rootfs', role, 'rootfs', config=False, makefileName='Makefile.muddle') # But we depend on busybox to have installed the various binaries first rule = muddled.depend.depend_one( None, Label.from_string('package:rootfs/installed'), Label.from_string('package:busybox/installed')) builder.ruleset.add(rule) # Deploy all our roles builder.by_default_deploy_list(roles)
def label_domain_sort(): """Test sorting labels with domain names in them. """ # Yes, apparently these are all legitimate label names # The domain names are the same as those used in the docstring for # utils.sort_domains() labels = [ Label.from_string('checkout:(a)fred/*'), Label.from_string('checkout:(+(1))fred/*'), Label.from_string('checkout:(-(2))fred/*'), Label.from_string('checkout:(a(b(c2)))fred/*'), Label.from_string('checkout:(a(b(c1)))fred/*'), Label.from_string('checkout:(+(1(+2(+4(+4)))))fred/*'), Label.from_string('checkout:(b(b))fred/*'), Label.from_string('checkout:(b)fred/*'), Label.from_string('checkout:(b(a))fred/*'), Label.from_string('checkout:(a(a))fred/*'), Label.from_string('checkout:(+(1(+2)))fred/*'), Label.from_string('checkout:(+(1(+2(+4))))fred/*'), Label.from_string('checkout:(+(1(+3)))fred/*'), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:(+(1))fred/*" " checkout:(+(1(+2)))fred/*" " checkout:(+(1(+2(+4))))fred/*" " checkout:(+(1(+2(+4(+4)))))fred/*" " checkout:(+(1(+3)))fred/*" " checkout:(-(2))fred/*" " checkout:(a)fred/*" " checkout:(a(a))fred/*" " checkout:(a(b(c1)))fred/*" " checkout:(a(b(c2)))fred/*" " checkout:(b)fred/*" " checkout:(b(a))fred/*" " checkout:(b(b))fred/*") # A specific test, which we originally got wrong labels = [ Label.from_string('checkout:(sub1)builds/checked_out'), Label.from_string('checkout:(sub1(sub4))builds/checked_out'), Label.from_string('checkout:(sub1(sub5))builds/checked_out'), Label.from_string('checkout:(sub2)builds/checked_out'), Label.from_string('checkout:(sub1(sub4))co0/checked_out'), Label.from_string('checkout:(sub1(sub5))co0/checked_out'), Label.from_string('checkout:(sub2(sub3))builds/checked_out'), Label.from_string('checkout:(sub2(sub3))co0/checked_out'), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels #print 'xxx' #for label in sorted_labels: # print ' ', str(label) #print 'xxx' # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:(sub1)builds/checked_out" " checkout:(sub1(sub4))builds/checked_out" " checkout:(sub1(sub4))co0/checked_out" " checkout:(sub1(sub5))builds/checked_out" " checkout:(sub1(sub5))co0/checked_out" " checkout:(sub2)builds/checked_out" " checkout:(sub2(sub3))builds/checked_out" " checkout:(sub2(sub3))co0/checked_out") # Another originally erroneous case l1 = Label.from_string( "checkout:(subdomain2(subdomain3))main_co/checked_out") l2 = Label.from_string("checkout:first_co/checked_out") print print 'xx', l1 print 'xx', l2 print 'xx l2 < l1', l2 < l1 assert l2 < l1 labels = [ Label.from_string("checkout:main_co/checked_out"), Label.from_string("checkout:(subdomain1)first_co/checked_out"), Label.from_string("checkout:(subdomain1)main_co/checked_out"), Label.from_string("checkout:(subdomain1)second_co/checked_out"), Label.from_string( "checkout:(subdomain1(subdomain3))first_co/checked_out"), Label.from_string( "checkout:(subdomain1(subdomain3))main_co/checked_out"), Label.from_string( "checkout:(subdomain1(subdomain3))second_co/checked_out"), Label.from_string("checkout:(subdomain2)first_co/checked_out"), Label.from_string("checkout:(subdomain2)main_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain3))main_co/checked_out"), Label.from_string("checkout:first_co/checked_out"), Label.from_string("checkout:second_co/checked_out"), Label.from_string("checkout:(subdomain2)second_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain3))first_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain3))second_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain4))first_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain4))main_co/checked_out"), Label.from_string( "checkout:(subdomain2(subdomain4))second_co/checked_out"), ] sorted_labels = sorted(labels) string_labels = map(str, labels) string_labels.sort() # Our properly sorted labels have changed order from that given assert sorted_labels != labels # It's not the same order as we'd get by sorting the labels as strings assert map(str, sorted_labels) != string_labels # It is this order... assert depend.label_list_to_string(sorted_labels) == ( "checkout:first_co/checked_out" " checkout:main_co/checked_out" " checkout:second_co/checked_out" " checkout:(subdomain1)first_co/checked_out" " checkout:(subdomain1)main_co/checked_out" " checkout:(subdomain1)second_co/checked_out" " checkout:(subdomain1(subdomain3))first_co/checked_out" " checkout:(subdomain1(subdomain3))main_co/checked_out" " checkout:(subdomain1(subdomain3))second_co/checked_out" " checkout:(subdomain2)first_co/checked_out" " checkout:(subdomain2)main_co/checked_out" " checkout:(subdomain2)second_co/checked_out" " checkout:(subdomain2(subdomain3))first_co/checked_out" " checkout:(subdomain2(subdomain3))main_co/checked_out" " checkout:(subdomain2(subdomain3))second_co/checked_out" " checkout:(subdomain2(subdomain4))first_co/checked_out" " checkout:(subdomain2(subdomain4))main_co/checked_out" " checkout:(subdomain2(subdomain4))second_co/checked_out")
def depend_unit_test(): """ Some fairly simple tests for the dependency solver. """ l1 = Label(utils.LabelType.Checkout, "co_1", "role_1", utils.LabelTag.CheckedOut) l2 = Label(utils.LabelType.Checkout, "co_1", "role_1", utils.LabelTag.Pulled) l3 = Label(utils.LabelType.Package, "pkg_1", "role_1", utils.LabelTag.PreConfig) l4 = Label(utils.LabelType.Deployment, "dep_1", "role_2", utils.LabelTag.Built) # Check label_from_string .. lx = Label.from_string("foo:bar{baz}/wombat[T]") lx_a = Label("foo", "bar", "baz", "wombat") assert lx == lx_a assert lx.transient assert not lx.system lx = Label.from_string("foo:bar/wombat[T]") lx_a = Label("foo", "bar", None, "wombat") assert lx == lx_a assert lx.transient assert not lx.system lx = Label.from_string("*:bar/wombat") assert (lx is not None) lx_a = Label("*", "bar", None, "wombat") assert lx == lx_a assert not lx.transient assert not lx.system lx = Label.from_string("*:wombat/*") assert lx is not None lx_a = Label("*", "wombat", None, "*") assert lx == lx_a assert not lx.transient assert not lx.system lx = Label.from_string(l1.__str__()) assert lx is not None assert lx == l1 lx = Label.from_string(l2.__str__()) assert lx is not None assert lx == l2 lx = Label.from_string(l3.__str__()) assert lx is not None assert lx == l3 lx = Label.from_string(l4.__str__()) assert lx is not None assert lx == l4 # Let's check that label matching works the way we think it does .. la1 = Label(type='*', name=l1.name, domain=l1.domain, role=l1.role, tag=l1.tag) la2 = Label(type=l1.type, name='*', domain=l1.domain, role=l1.role, tag=l1.tag) la3 = Label(type=l1.type, name='*', domain=l1.domain, role='*', tag=l1.tag) la4 = l1.copy_with_tag('*') assert l1.match(l1) == 0 assert l2.match(l1) is None assert la1.match(l1) == -1 assert l1.match(la1) == -1 assert (l2.match(la4)) == -1 assert l1.match(la3) == -2 r1 = depend.Rule(l1, pkg.NoAction()) r2 = depend.Rule(l2, pkg.NoAction()) r2.add(l1) r3 = depend.Rule(l3, pkg.NoAction()) r4 = depend.Rule(l4, pkg.NoAction()) r3.add(l2) r4.add(l3) r4.add(l2) rs = depend.RuleSet() rs.add(r1) rs.add(r2) rs.add(r3) rs.add(r4) assert str(rs).strip() == """\ ----- checkout:co_1{role_1}/checked_out <-NoAction-- [ ] checkout:co_1{role_1}/pulled <-NoAction-- [ checkout:co_1{role_1}/checked_out ] deployment:dep_1{role_2}/built <-NoAction-- [ checkout:co_1{role_1}/pulled, package:pkg_1{role_1}/preconfig ] package:pkg_1{role_1}/preconfig <-NoAction-- [ checkout:co_1{role_1}/pulled ] -----""" r3_required_for = depend.needed_to_build(rs, l3) assert depend.rule_list_to_string( r3_required_for ) == "[ checkout:co_1{role_1}/checked_out <-NoAction-- [ ], checkout:co_1{role_1}/pulled <-NoAction-- [ checkout:co_1{role_1}/checked_out ], package:pkg_1{role_1}/preconfig <-NoAction-- [ checkout:co_1{role_1}/pulled ], ]" r2_required_by = depend.required_by(rs, l2) assert depend.rule_list_to_string( r2_required_by ) == "[ checkout:co_1{role_1}/pulled, deployment:dep_1{role_2}/built, package:pkg_1{role_1}/preconfig, ]"
def relative(builder, co_dir, co_name, repo_relative=None, rev=None, branch=None): """ A two-level version of checkout.simple.relative(). It attempts to check out <co_dir>/<co_name> (but see below). <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, 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"). If <repo_relative> is not None, then the repository <base_url>/<repo_relative> ... In the normal case, the location in the repository and in the checkout is assumed the same (i.e., <co_dir>/<co_name>). So, for instance, with co_dir="A" and co_name="B", the repository would have:: <base_url>/A/B which we would check out into:: src/A/B Occasionally, though, the repository is organised differently, so for instance, one might want to checkout:: <base_url>/B into:: src/A/B In this latter case, one can use the 'repo_relative' argument, to say where the checkout is relative to the repository's "base". So, in the example above, we still have co_dir="A" and co_name="B", but we also want to say repo_relative=B. """ base_repo = builder.build_desc_repo if repo_relative: repo_co_dir, repo_co_name = os.path.split(repo_relative) repo = base_repo.copy_with_changes(repo_co_name, prefix=repo_co_dir, revision=rev, branch=branch) else: repo = base_repo.copy_with_changes(co_name, prefix=co_dir, 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 describe_to(builder): role = 'omap' roles = ['omap'] builder.add_default_role(role) # filedep.deploy(builder, target_dir, name, roles) # # Register a file deployment. # # The deployment will take the roles specified in the role list, and build # them into a deployment at deploy/[name]. # # The deployment should eventually be located at target_dir. filedep.deploy(builder, '/', 'omap', roles) # Both Linux and Busybox share some environment we'd like to specify # only once. The mechanism for doing this is a little bit cunning label = Label.from_string('package:*{omap}/*') # i.e., all our packages # We can retrieve the "environment" (technically, an environment Store) # that will be used for that label - this will create one if it doesn't # exist yet env = builder.get_environment_for(label) # And adding values to that is simple env.set("MUDDLE_CROSS_COMPILE", "/opt/codesourcery/arm-2008q3/bin/arm-none-linux-gnueabi-") env.set("MUDDLE_ARCH", "arm") # There's a variety of things we need on (this, the host) system # in order to build - I hope I've got this right (difficult to tell # as I already have some stuff installed on *my* development system) aptget.simple(builder, 'development_packages', role, ['zlib1g-dev', 'uboot-mkimage']) # According to http://omappedia.org/wiki/LinuxOMAP_Kernel_Project, we get # our OMAP kernel from: muddled.checkouts.simple.absolute(builder, 'omap_kernel', 'git+git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git') # Once we've got one worked out, we'll also want to retrieve a default # kernel configuration (we don't, eventually, want to make the developer # have to work that out every time!) # We'll aim to make that with an out-of-tree makefile # We could make a tailored subclass of muddled.pkgs.linux_kernel, and use # that to build our kernel. I may still do that once I've figured out how # it is different (one notable change is we're building uImage instead of # zImage). For now, it's probably easier to have a Makefile.muddle make.medium(builder, name = "omap_kernel", # package name roles = roles, checkout = "helpers", deps = [], makefileName = os.path.join("omap_kernel","Makefile.muddle")) muddled.pkg.package_depends_on_checkout(builder.ruleset, "omap_kernel", # this package role, # in this role "omap_kernel") # depends on this checkout # On top of that, we want to build busybox # # According to the busybox website, we can retrieve sources via git: # # To grab a copy of the BusyBox repository using anonymous git access:: # # git clone git://busybox.net/busybox.git # # Once you have the repository, stable branches can be checked out by # doing:: # # git checkout remotes/origin/1_NN_stable # # Once you've checked out a copy of the source tree, you can update your # source tree at any time so it is in sync with the latest and greatest by # entering your BusyBox directory and running the command:: # # git pull # So, for the moment, at least, let's go with the latest from source # control (when we're finalising this, we're maybe better identifying # a particular release to stick to) muddled.checkouts.simple.absolute(builder, 'busybox', 'git+git://busybox.net/busybox.git') # We'll aim to make that with an out-of-tree makefile # # 'deps' is a list of package names, which our make depends on. # # Specifically, for each <name> in 'deps', and for each <role> in 'roles', # we will depend on "package:<name>{<role>}/postinstalled" make.medium(builder, name = "busybox", # package name roles = roles, checkout = "helpers", deps = [ 'omap_kernel' ], makefileName = os.path.join("busybox","Makefile.muddle")) # And we also depend on having actually checked out busybox muddled.pkg.package_depends_on_checkout(builder.ruleset, "busybox", # this package role, # in this role "busybox", # depends on this checkout None) # Can we use the same bootloader and such that we already had for the # android build? # The bootloader and related items, which go into the FAT32 partition on # the flash card, are retrieved from the net (eventually, I hope we'll be # building u-boot, but for now the binary should do) muddled.checkouts.simple.absolute(builder, 'MLO', 'wget+http://free-electrons.com/pub/demos/beagleboard/android/MLO') muddled.checkouts.simple.absolute(builder, 'u-boot', 'wget+http://free-electrons.com/pub/demos/beagleboard/android/u-boot.bin') # We need some way of getting them installed - let's foreshadow the day when # we actually want to build u-boot ourselves, and pretend make.medium(builder, name = "u-boot", # package name roles = roles, checkout = "helpers", deps = [], makefileName = os.path.join("u-boot","Makefile.muddle")) muddled.pkg.package_depends_on_checkout(builder.ruleset, "u-boot", # this package role, # in this role "u-boot", # depends on this checkout None) # Oh, and this one as well... rule = muddled.depend.depend_one(None, Label.from_string('package:u-boot{%s}/built'%role), Label.from_string('checkout:MLO/checked_out')) builder.ruleset.add(rule) # And, of course, we need (the rest of) our Linux filesystem muddled.checkouts.simple.absolute(builder, 'rootfs', 'bzr+ssh://[email protected]//opt/kynesim/projects/052/rootfs') make.simple(builder, 'rootfs', role, 'rootfs', config=False, makefileName='Makefile.muddle') # But we depend on busybox to have installed the various binaries first rule = muddled.depend.depend_one(None, Label.from_string('package:rootfs/installed'), Label.from_string('package:busybox/installed')) builder.ruleset.add(rule) # Deploy all our roles builder.by_default_deploy_list(roles)