Exemple #1
0
def add_digest(impl, alg_name):
    alg = manifest.get_algorithm(alg_name)

    # Scan through the existing digests
    # - If we've already got the one we need, return
    # - Otherwise, find a cached implementation we can use
    existing_path = None
    for a, value in digests(impl):
        if a in ('sha1', 'sha1new', 'sha256'):
            digest = '%s=%s' % (a, value)
        else:
            digest = '%s_%s' % (a, value)
        if a == alg_name:
            return False  # Already signed with this algorithm
        if not existing_path:
            try:
                existing_path = stores.lookup(digest)
                if existing_path:
                    existing_digest = digest
            except NotStored:
                pass  # OK

    if existing_path is None:
        print("No implementations of %s cached; can't calculate new digest" %
              get_version(impl))
        return False

    info("Verifying %s", existing_path)
    manifest.verify(existing_path, existing_digest)

    print("Adding new digest to version %s" % get_version(impl))

    new_digest = alg.new_digest()
    for line in alg.generate_manifest(existing_path):
        new_digest.update((line + '\n').encode())

    for md in xmltools.children(impl, 'manifest-digest'):
        break
    else:
        md = xmltools.create_element(impl, 'manifest-digest')
    _, digest_value = manifest.splitID(alg.getID(new_digest))
    md.setAttribute(alg_name, digest_value)

    return True
Exemple #2
0
def add_digest(impl, alg_name):
	alg = manifest.get_algorithm(alg_name)
	
	# Scan through the existing digests
	# - If we've already got the one we need, return
	# - Otherwise, find a cached implementation we can use
	existing_path = None
	for a, value in digests(impl):
		digest = '%s=%s' % (a, value)
		if a == alg_name:
			return False			# Already signed with this algorithm
		if not existing_path:
			try:
				existing_path = stores.lookup(digest)
				if existing_path:
					existing_digest = digest
			except NotStored:
				pass		# OK

	if existing_path is None:
		print "No implementations of %s cached; can't calculate new digest" % get_version(impl)
		return False

	info("Verifying %s", existing_path)
	manifest.verify(existing_path, existing_digest)

	print "Adding new digest to version %s" % get_version(impl)

	new_digest = alg.new_digest()
	for line in alg.generate_manifest(existing_path):
		new_digest.update(line + '\n')

	for md in xmltools.children(impl, 'manifest-digest'):
		break
	else:
		md = xmltools.create_element(impl, 'manifest-digest')
	md.setAttribute(alg_name, new_digest.hexdigest())

	return True
Exemple #3
0
def merge(data, local):
	local_doc = minidom.parse(local)
	master_doc = minidom.parseString(data)

	known_ids = set()
	def check_unique(elem):
		impl_id = impl.getAttribute("id")
		if impl_id in known_ids:
			raise Exception("Duplicate ID " + impl_id)
		known_ids.add(impl_id)

	for impl in find_impls(master_doc.documentElement):
		check_unique(impl)

	# Merge each implementation in the local feed in turn (normally there will only be one)
	for impl in find_impls(local_doc.documentElement):
		check_unique(impl)

		# 1. Get the context of the implementation to add. This is:
		#    - The set of its requirements
		#    - The set of its commands
		#    - Its attributes
		new_impl_context = Context(impl)

		# 2. For each <group> in the master feed, see if it provides a compatible context:
		#    - A subset of the new implementation's requirements
		#    - A subset of the new implementation's command names
		#    - A subset of the new implementation's attributes (names, not values)
		#    Choose the most compatible <group> (the root counts as a minimally compatible group)

		best_group = ((1, 0, 0), master_doc.documentElement)	# (score, element)

		for group in find_groups(master_doc.documentElement):
			group_context = Context(group)
			score = score_subset(group_context, new_impl_context)
			if score > best_group[0]:
				best_group = (score, group)

		group = best_group[1]
		group_context = Context(group)

		if new_impl_context.has_main_and_run:
			# If the existing group doesn't have the same main value then we'll need a new group. Otherwise,
			# we're likely to override the command by having main on the implementation element.
			current_group_main = group_context.attribs.get((None, 'main'), None)
			need_new_group_for_main = current_group_main != new_impl_context.attribs[(None, 'main')]
		else:
			need_new_group_for_main = False

		new_commands = []
		for name_expr, new_command in new_impl_context.commands.items():
			if need_new_group_for_main and name_expr[0] == 'run':
				# If we're creating a new <group main='...'> then we can't inherit an existing <command name='run'/>,
				old_command = None
			else:
				old_command = group_context.commands.get(name_expr, None)
			if not (old_command and nodesEqual(old_command, new_command)):
				new_commands.append(xmltools.import_node(master_doc, new_command))

		# If we have additional requirements or commands, we'll need to create a subgroup and add them
		if len(new_impl_context.requires) > len(group_context.requires) or new_commands or need_new_group_for_main:
			subgroup = xmltools.create_element(group, 'group')
			group = subgroup
			#group_context = Context(group)
			for x in new_impl_context.requires:
				for y in group_context.requires:
					if nodesEqual(x, y): break
				else:
					req = xmltools.import_node(master_doc, x)
					#print "Add", req
					xmltools.insert_element(req, group)
			for c in new_commands:
				xmltools.insert_element(c, group)

			if need_new_group_for_main:
				group.setAttribute('main', new_impl_context.attribs[(None, 'main')])
				# We'll remove it from the <implementation> below, when cleaning up duplicates

			group_context = Context(group)

		new_impl = xmltools.import_node(master_doc, impl)

		# Attributes might have been set on a parent group; move to the impl
		for name in new_impl_context.attribs:
			#print "Set", name, value
			xmltools.add_attribute_ns(new_impl, name[0], name[1], new_impl_context.attribs[name])

		for name, value in new_impl.attributes.itemsNS():
			if name[0] == XMLNS_NAMESPACE or \
			   (name in group_context.attribs and group_context.attribs[name] == value):
				#print "Deleting duplicate attribute", name, value
				new_impl.removeAttributeNS(name[0], name[1])

		xmltools.insert_element(new_impl, group)

	return master_doc.toxml('utf-8')
Exemple #4
0
def merge(data, local):
	local_doc = minidom.parse(local)
	master_doc = minidom.parseString(data)

	# Merge each implementation in the local feed in turn (normally there will only be one)
	for impl in find_impls(local_doc.documentElement):
		# 1. Get the context of the implementation to add. This is:
		#    - The set of its requirements
		#    - The set of its commands
		#    - Its attributes
		new_impl_context = Context(impl)

		# 2. For each <group> in the master feed, see if it provides a compatible context:
		#    - A subset of the new implementation's requirements
		#    - A subset of the new implementation's command names
		#    - A subset of the new implementation's attributes (names, not values)
		#    Choose the most compatible <group> (the root counts as a minimally compatible group)

		best_group = ((1, 0, 0), master_doc.documentElement)	# (score, element)

		for group in find_groups(master_doc.documentElement):
			group_context = Context(group)
			score = score_subset(group_context, new_impl_context)
			if score > best_group[0]:
				best_group = (score, group)

		group = best_group[1]
		group_context = Context(group)

		new_commands = []
		for name, new_command in new_impl_context.commands.iteritems():
			old_command = group_context.commands.get(name, None)
			if not (old_command and nodesEqual(old_command, new_command)):
				new_commands.append(master_doc.importNode(new_command, True))

		# If we have additional requirements, we'll need to create a subgroup and add them
		if len(new_impl_context.requires) > len(group_context.requires) or new_commands:
			subgroup = xmltools.create_element(group, 'group')
			group = subgroup
			#group_context = Context(group)
			for x in new_impl_context.requires:
				for y in group_context.requires:
					if nodesEqual(x, y): break
				else:
					req = master_doc.importNode(x, True)
					#print "Add", req
					xmltools.insert_element(req, group)
			for c in new_commands:
				xmltools.insert_element(c, group)

		new_impl = master_doc.importNode(impl, True)

		# Attributes might have been set on a parent group; move to the impl
		for name in new_impl_context.attribs:
			#print "Set", name, value
			xmltools.add_attribute_ns(new_impl, name[0], name[1], new_impl_context.attribs[name])

		for name, value in new_impl.attributes.itemsNS():
			if name[0] == XMLNS_NAMESPACE or \
			   (name in group_context.attribs and group_context.attribs[name] == value):
				#print "Deleting duplicate attribute", name, value
				new_impl.removeAttributeNS(name[0], name[1])

		xmltools.insert_element(new_impl, group)

	return master_doc.toxml()