def validate(self): p = self.target_dir / ".build.manifest" if not p.exists(): return [], [], [] ignorer = utils.ignore_matcher(DEFAULT_IGNORES) a, c, d = utils.delta_signatures(p, ignorer) for f in a: log.warn( "Added unexpected file, should be in a base layer: %s", f) for f in c: log.warn( "Changed file owned by another layer: %s", f) for f in d: log.warn( "Deleted a file owned by another layer: %s", f) if a or c or d: if self.force is True: log.info( "Continuing with known changes to target layer. " "Changes will be overwritten") else: raise ValueError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def inspect(charm, force_styling=False): tw = utils.TermWriter(force_styling=force_styling) manp = charm / ".composer.manifest" comp = charm / "composer.yaml" if not manp.exists() or not comp.exists(): return manifest = json.loads(manp.text()) composer = yaml.load(comp.open()) a, c, d = utils.delta_signatures(manp) # ordered list of layers used for legend layers = list(manifest['layers']) def get_depth(e): rel = e.relpath(charm) depth = len(rel.splitall()) - 2 return rel, depth def get_suffix(rel): suffix = "" if rel in a: suffix = "+" elif rel in c: suffix = "*" return suffix def get_color(rel): # name of layer this belongs to color = tw.term.normal if rel in manifest['signatures']: layer = manifest['signatures'][rel][0] layer_key = layers.index(layer) color = getattr(tw, theme.get(layer_key, "normal")) else: if entry.isdir(): color = tw.blue return color tw.write("Inspect %s\n" % composer["is"]) for layer in layers: tw.write("# {color}{layer}{t.normal}\n", color=getattr(tw, theme.get(layers.index(layer), "normal")), layer=layer) tw.write("\n") tw.write("{t.blue}{target}{t.normal}\n", target=charm) ignorer = utils.ignore_matcher(config.DEFAULT_IGNORES) walk = sorted(utils.walk(charm, get_depth), key=lambda x: x[1][0]) for i in range(len(walk) - 1): entry, (rel, depth) = walk[i] nEnt, (nrel, ndepth) = walk[i + 1] if not ignorer(rel): continue tw.write("{prefix}{layerColor}{entry} " "{t.bold}{suffix}{t.normal}\n", prefix=get_prefix(walk, i, depth, ndepth), layerColor=get_color(rel), suffix=get_suffix(rel), entry=rel.name)
def exec_plan(self, plan=None, layers=None): signatures = {} cont = True for phase in self.PHASES: for tactic in plan: if phase == "lint": cont &= tactic.lint() if cont is False and self.force is not True: return elif phase == "read": # We use a read (into memory phase to make layer comps # simpler) tactic.read() elif phase == "call": tactic() elif phase == "sign": sig = tactic.sign() if sig: signatures.update(sig) new_repo = not self.manifest.exists() if new_repo: added, changed, removed = set(), set(), set() else: ignores = utils.ignore_matcher(DEFAULT_IGNORES) added, changed, _ = utils.delta_signatures(self.manifest, ignores) removed = self.clean_removed(signatures) # write out the sigs if "sign" in self.PHASES: self.write_signatures(signatures, layers) if self.report: self.write_report(new_repo, added, changed, removed)
def validate(self): self._validate_charm_repo() if not self.manifest.exists(): return [], [], [] a, c, d = utils.delta_signatures(self.manifest) for f in a: log.warn( "Conflict: File in destination directory " "was added after charm build: %s", f) for f in c: log.warn( "Conflict: File in destination directory " "was modified after charm build: %s", f) for f in d: log.warn( "Conflict: File in destination directory " "was deleted after charm build: %s", f) if a or c or d: if self.force is True: log.info("Continuing with known changes to target layer. " "Changes will be overwritten") else: raise BuildError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def exec_plan(self, plan=None, layers=None): signatures = {} cont = True for phase in self.PHASES: for tactic in plan: if phase == "lint": cont &= tactic.lint() if cont is False and self.force is not True: # no message, reason will already have been logged raise BuildError() elif phase == "read": # We use a read (into memory phase to make layer comps # simpler) tactic.read() elif phase == "call": tactic() elif phase == "sign": sig = tactic.sign() if sig: signatures.update(sig) new_repo = not self.manifest.exists() if new_repo: added, changed, removed = set(), set(), set() else: added, changed, _ = utils.delta_signatures(self.manifest) removed = self.clean_removed(signatures) # write out the sigs if "sign" in self.PHASES: self.write_signatures(signatures, layers) if self.report: self.write_report(new_repo, added, changed, removed)
def validate(self): self._validate_charm_repo() if not self.manifest.exists(): return [], [], [] a, c, d = utils.delta_signatures(self.manifest) for f in a: log.warn( "Added unexpected file, should be in a base layer: %s", f) for f in c: log.warn( "Changed file owned by another layer: %s", f) for f in d: log.warn( "Deleted a file owned by another layer: %s", f) if a or c or d: if self.force is True: log.info( "Continuing with known changes to target layer. " "Changes will be overwritten") else: raise BuildError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def validate(self): self._validate_charm_repo() if not self.manifest.exists(): return [], [], [] a, c, d = utils.delta_signatures(self.manifest) for f in a: log.warn("Conflict: File in destination directory " "was added after charm build: %s", f) for f in c: log.warn("Conflict: File in destination directory " "was modified after charm build: %s", f) for f in d: log.warn("Conflict: File in destination directory " "was deleted after charm build: %s", f) if a or c or d: if self.force is True: log.info( "Continuing with known changes to target layer. " "Changes will be overwritten") else: raise BuildError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def validate(self): p = self.target_dir / ".composer.manifest" if not p.exists(): return [], [], [] ignorer = utils.ignore_matcher(DEFAULT_IGNORES) a, c, d = utils.delta_signatures(p, ignorer) for f in a: log.warn( "Added unexpected file, should be in a base layer: %s", f) for f in c: log.warn( "Changed file owned by another layer: %s", f) for f in d: log.warn( "Deleted a file owned by another layer: %s", f) if a or c or d: if self.force is True: log.info( "Continuing with known changes to target layer. " "Changes will be overwritten") else: raise ValueError( "Unable to continue due to unexpected modifications (try --force)") return a, c, d
def validate(self): if not (self.name and str(self.name)[0] in string.ascii_lowercase): raise BuildError('Charm name must start with a lower-case letter') for cls in (InterfaceFetcher, LayerFetcher): if cls.OLD_ENVIRON in os.environ and cls.ENVIRON not in os.environ: log.warning('DEPRECATED: {} environment variable; ' 'please use {} instead'.format( cls.OLD_ENVIRON, cls.ENVIRON)) self._validate_charm_repo() if not self.manifest.exists(): return [], [], [] a, c, d = utils.delta_signatures(self.manifest) for f in a: log.warn( "Conflict: File in destination directory " "was added after charm build: %s", f) for f in c: log.warn( "Conflict: File in destination directory " "was modified after charm build: %s", f) for f in d: log.warn( "Conflict: File in destination directory " "was deleted after charm build: %s", f) if a or c or d: if self.force is True: log.info("Continuing with known changes to target layer. " "Changes will be overwritten") else: raise BuildError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def validate(self): if not (self.name and str(self.name)[0] in string.ascii_lowercase): raise BuildError('Charm name must start with a lower-case letter') for cls in (InterfaceFetcher, LayerFetcher): if cls.OLD_ENVIRON in os.environ and cls.ENVIRON not in os.environ: log.warning('DEPRECATED: {} environment variable; ' 'please use {} instead'.format(cls.OLD_ENVIRON, cls.ENVIRON)) self._validate_charm_repo() if not self.manifest.exists(): return [], [], [] a, c, d = utils.delta_signatures(self.manifest) for f in a: log.warn("Conflict: File in destination directory " "was added after charm build: %s", f) for f in c: log.warn("Conflict: File in destination directory " "was modified after charm build: %s", f) for f in d: log.warn("Conflict: File in destination directory " "was deleted after charm build: %s", f) if a or c or d: if self.force is True: log.info( "Continuing with known changes to target layer. " "Changes will be overwritten") else: raise BuildError( "Unable to continue due to unexpected modifications " "(try --force)") return a, c, d
def inspect(charm, force_styling=False, annotate=False): tw = utils.TermWriter(force_styling=force_styling) manp = charm / ".build.manifest" comp = charm / "layer.yaml" if not manp.exists() or not comp.exists(): return manifest = json.loads(manp.text()) composer = yaml.safe_load(comp.open()) a, c, d = utils.delta_signatures(manp) # ordered list of layers used for legend if isinstance(manifest['layers'][0], dict): layers = [layer['url'] for layer in manifest['layers']] else: layers = list(manifest['layers']) layers.reverse() while layers[0].startswith('interface:'): layers.append(layers.pop(0)) def get_depth(e): rel = e.relpath(charm) depth = len(rel.splitall()) - 2 return rel, depth def get_suffix(rel): suffix = "" if rel in a: suffix = "+" elif rel in c: suffix = "*" return suffix def get_color(rel): # name of layer this belongs to color = tw.term.normal if rel in manifest['signatures']: layer = manifest['signatures'][rel][0] if layer in layers: layer_key = layers.index(layer) else: # handle special build created artifacts, which have # a "layer name" of "build" (mostly the manifest itself) layer_key = -1 color = getattr(tw, theme.get(layer_key, "normal")) else: if entry.isdir(): color = tw.blue return color tw.write("Inspect %s\n" % composer["is"]) if tw.does_styling or force_styling: tw.write("\n") tw.write("Color key:\n") for i, layer in enumerate(layers): tw.write("# {color}{layer}{t.normal}\n", color=getattr(tw, theme.get(i, "normal")), layer=layer) else: # force annotations if we can't use color annotate = True tw.write("\n") tw.write("{t.blue}{target}{t.normal}\n", target=charm) ignorer = utils.ignore_matcher(config.DEFAULT_IGNORES) walk = sorted(utils.walk(charm, get_depth), key=lambda x: x[1][0]) for i in range(len(walk) - 1): entry, (rel, depth) = walk[i] nEnt, (nrel, ndepth) = walk[i + 1] if not ignorer(rel): continue if annotate and rel in manifest['signatures']: layer_name = manifest['signatures'][rel][0] if layer_name == 'build': # handle special build created artifacts, which have # a "layer name" of "build" (mostly the manifest itself) annotation = ' ({}build artifact{})'.format(tw.bright_black, tw.normal) else: annotation = ' (from {}{}{})'.format(get_color(rel), layer_name, tw.normal) else: annotation = '' tw.write("{prefix}{layerColor}{entry} " "{t.bold}{suffix}{t.normal}{annotation}\n", prefix=get_prefix(walk, i, depth, ndepth), layerColor=get_color(rel), suffix=get_suffix(rel), entry=rel.name, annotation=annotation)
def inspect(charm, force_styling=False): tw = utils.TermWriter(force_styling=force_styling) manp = charm / ".composer.manifest" comp = charm / "composer.yaml" if not manp.exists() or not comp.exists(): return manifest = json.loads(manp.text()) composer = yaml.load(comp.open()) a, c, d = utils.delta_signatures(manp) # ordered list of layers used for legend layers = list(manifest['layers']) def get_depth(e): rel = e.relpath(charm) depth = len(rel.splitall()) - 2 return rel, depth def get_suffix(rel): suffix = "" if rel in a: suffix = "+" elif rel in c: suffix = "*" return suffix def get_color(rel): # name of layer this belongs to color = tw.term.normal if rel in manifest['signatures']: layer = manifest['signatures'][rel][0] layer_key = layers.index(layer) color = getattr(tw, theme.get(layer_key, "normal")) else: if entry.isdir(): color = tw.blue return color tw.write("Inspect %s\n" % composer["is"]) for layer in layers: tw.write("# {color}{layer}{t.normal}\n", color=getattr(tw, theme.get( layers.index(layer), "normal")), layer=layer) tw.write("\n") tw.write("{t.blue}{target}{t.normal}\n", target=charm) ignorer = utils.ignore_matcher(config.DEFAULT_IGNORES) walk = sorted(utils.walk(charm, get_depth), key=lambda x: x[1][0]) for i in range(len(walk) - 1): entry, (rel, depth) = walk[i] nEnt, (nrel, ndepth) = walk[i + 1] if not ignorer(rel): continue tw.write("{prefix}{layerColor}{entry} " "{t.bold}{suffix}{t.normal}\n", prefix=get_prefix(walk, i, depth, ndepth), layerColor=get_color(rel), suffix=get_suffix(rel), entry=rel.name)
def inspect(charm, force_styling=False, annotate=False): tw = utils.TermWriter(force_styling=force_styling) manp = charm / ".build.manifest" comp = charm / "layer.yaml" if not manp.exists() or not comp.exists(): return manifest = json.loads(manp.text()) composer = yaml.safe_load(comp.open()) a, c, d = utils.delta_signatures(manp) # ordered list of layers used for legend if isinstance(manifest['layers'][0], dict): layers = [layer['url'] for layer in manifest['layers']] else: layers = list(manifest['layers']) layers.reverse() while layers[0].startswith('interface:'): layers.append(layers.pop(0)) def get_depth(e): rel = e.relpath(charm) depth = len(rel.splitall()) - 2 return rel, depth def get_suffix(rel): suffix = "" if rel in a: suffix = "+" elif rel in c: suffix = "*" return suffix def get_color(rel): # name of layer this belongs to color = tw.term.normal if rel in manifest['signatures']: layer = manifest['signatures'][rel][0] if layer in layers: layer_key = layers.index(layer) else: # handle special build created artifacts, which have # a "layer name" of "build" (mostly the manifest itself) layer_key = -1 color = getattr(tw, theme.get(layer_key, "normal")) else: if entry.isdir(): color = tw.blue return color tw.write("Inspect %s\n" % composer["is"]) if tw.does_styling or force_styling: tw.write("\n") tw.write("Color key:\n") for i, layer in enumerate(layers): tw.write("# {color}{layer}{t.normal}\n", color=getattr(tw, theme.get(i, "normal")), layer=layer) else: # force annotations if we can't use color annotate = True tw.write("\n") tw.write("{t.blue}{target}{t.normal}\n", target=charm) ignorer = utils.ignore_matcher(config.DEFAULT_IGNORES) walk = sorted(utils.walk(charm, get_depth), key=lambda x: x[1][0]) for i in range(len(walk) - 1): entry, (rel, depth) = walk[i] nEnt, (nrel, ndepth) = walk[i + 1] if not ignorer(rel): continue if annotate and rel in manifest['signatures']: layer_name = manifest['signatures'][rel][0] if layer_name == 'build': # handle special build created artifacts, which have # a "layer name" of "build" (mostly the manifest itself) annotation = ' ({}build artifact{})'.format( tw.bright_black, tw.normal) else: annotation = ' (from {}{}{})'.format(get_color(rel), layer_name, tw.normal) else: annotation = '' tw.write( "{prefix}{layerColor}{entry} " "{t.bold}{suffix}{t.normal}{annotation}\n", prefix=get_prefix(walk, i, depth, ndepth), layerColor=get_color(rel), suffix=get_suffix(rel), entry=rel.name, annotation=annotation)