def check_caflib(path, src, env): try: info('Loading hook "{}"'.format(path)) module = imp.new_module(path.stem) exec(compile(path.open().read(), path.name, 'exec'), module.__dict__) except: import traceback traceback.print_exc() error('There was an error while reading hook "{}"'.format(path)) imports = [inspect.getmodule(obj) for _, obj in inspect.getmembers(module)] imports = set(Path(i.__file__) for i in imports if i) imports = [i for i in imports if 'caflib' in i.parts] files = [] for i in imports: if i.name != '__init__.py': files.append(i) else: _reported.append(( warn, 'Hook "{}" is loading whole caflib'.format(path))) files.extend(i.parent.glob('**/*.py')) files = sorted(set(files)) if files: env['PYTHONPATH'].append(caflib_path) for file in files: relpath = '/'.join(dropwhile(lambda x: x != 'caflib', file.parts)) with (Path(caflib_path)/relpath).open() as f: h = md5(f.read().encode()).hexdigest() src = '{}\n# md5 {}: {}' \ .format(src, relpath, h) return src
def init(caf): """ Initialize the Caf repository. Usage: caf init By default create directory in .caf/db. If 'cache' is defined in ~/.config/caf/conf.yaml, the repository is created there and symlinked to .caf/db, otherwise it is created locally. """ if 'cache' in caf.conf: timestamp = get_timestamp() cache_path = Path(caf.conf['cache'])/'{}_{}'.format(Path().resolve().name, timestamp) mkdir(cache_path) relink(cache_path, caf.cache, relative=False) else: cache_path = caf.cache if cache_path.exists(): error('{} exists, cannot overwrite'.format(cache_path)) mkdir(cache_path) info('Initializing an empty repository at {}.'.format(cache_path)) mkdir(caf.cellar) mkdir(caf.brewery) with open('.gitignore', 'w') as f: f.write('\n'.join(['.caf'])) with open(os.devnull, 'w') as null: sp.call(['git', 'init'], stdout=null) sp.call(['git', 'add', 'caf', 'cscript.py', '.gitignore'], stdout=null) sp.call(['git', 'commit', '-m', 'initial commit'], stdout=null)
def build(self, path): """Prepare, lock and store the task. Check if not already locked. Touch (link in children, save chilren to .caf/children). Check if needed children are already sealed. Check if children are already locked. Prepare task. Get hashes. Lock task with hashes. Check if a task has been already stored previously and if not, store it and relink children. """ with timing('task init'): if not path.is_dir(): mkdir(path) self.path = Path(path).resolve() if self.is_locked(): warn('{} already locked'.format(self)) return if not self.is_touched(): self.touch() for linkname, link in self.links.items(): if link.needed and not link.task.is_sealed(): warn('{}: dependency "{}" not sealed'.format(self, linkname)) return if not all(child.is_locked() for child in self.children): return with timing('prepare'): self.prepare() with timing('hash'): hashes = self.get_hashes() with timing('lock'): self.lock(hashes) myhash = get_file_hash(self.path/'.caf/lock') with timing('storing'): cellarpath = self.ctx.cellar/str_to_path(myhash) if cellarpath.is_dir(): env_file = Path(self.path/'.caf/env') if env_file.is_file(): env_file.rename(cellarpath/'.caf/env') shutil.rmtree(str(self.path)) else: info('Stored new task {}'.format(self)) mkdir(cellarpath.parent, parents=True, exist_ok=True) self.path.rename(cellarpath) relink(cellarpath, self.path) self.path = cellarpath with timing('linking deps'): self.link_deps()
def __init__(self, path_or_stringio): try: text = path_or_stringio.getvalue() except AttributeError: self.key = path = Path(path_or_stringio) self.name = path.name if self.key not in Template._cache: try: Template._cache[self.key] = path.open().read() info('Loading template "{}"'.format(path)) except FileNotFoundError: error('Template "{}" does not exist'.format(path)) else: self.key = sha1(text.encode()).hexdigest() self.name = self.key[-7:] if self.key not in Template._cache: Template._cache[self.key] = text info('Loading anonymous template')
def store_link_file(self, source, target=None): try: text = source.getvalue() except AttributeError: pass else: assert target self.store_link_text(text, target) return if not target: target = source if Path(source).is_dir(): (self.path/target).mkdir() return filehash = get_file_hash(Path(source)) cellarpath = self.ctx.cellar/str_to_path(filehash) if not cellarpath.is_file(): info('Stored new file "{}"'.format(source)) mkdir(cellarpath.parent, parents=True, exist_ok=True) shutil.copy(str(source), str(cellarpath)) make_nonwritable(cellarpath) with cd(self.path): relink(os.path.relpath(str(cellarpath)), target) self.files[str(target)] = cellarpath
def store_link_text(self, text, target, label=None): h = hashlib.new(hashf) h.update(text.encode()) texthash = h.hexdigest() cellarpath = self.ctx.cellar/str_to_path(texthash) if not cellarpath.is_file(): if label is True: info('Stored new file "{}"'.format(target)) elif label: info('Stored new text labeled "{}"'.format(label)) else: info('Stored new text') mkdir(cellarpath.parent, parents=True, exist_ok=True) with cellarpath.open('w') as f: f.write(text) make_nonwritable(cellarpath) with cd(self.path): relink(os.path.relpath(str(cellarpath)), target) self.files[target] = cellarpath