def find_command(name, warn=False): path = which(name) if path: print style_note('%s:' % name, path) else: if warn: print style_warning('cannot find %s' % name) else: print style_error('cannot find %s' % name) return 1
def rm(args): res = 0 con = args.assert_home().db.connect() for pattern in args.patterns: cur = con.execute('DELETE FROM development_packages WHERE name GLOB ?', [pattern]) if not cur.rowcount: print style_warning('No dev packages matching "%s"' % pattern) res = 1 return res
def list_(args): home = args.assert_home() rows = list(home.db.execute('SELECT * FROM repositories')) if not rows: print style_warning('No repositories.') return max_len = max(len(row['name']) for row in rows) for row in rows: env_repo = EnvironmentRepo(row, home=home) if env_repo.exists: print style_note( env_repo.name, '%s/%s' % (env_repo.remote_name, env_repo.branch_name), env_repo.remotes().get(env_repo.remote_name, '') + ' --default' if row['is_default'] else '', )
def summarize_rev_distance( local, remote, local_name='You', local_verb='are', remote_name='', fork_action='please rebase.', ahead_action='you may push.', behind_action='please pull.', indent=' ', ): if local and remote: print indent + style_warning( '%s and %s have forked%s' % (local_name, remote_name or 'the remote', '; ' + fork_action if fork_action else '.')) print indent + style_warning( 'There are %d local commit%s, and %d remote commit%s.' % ( local, 's' if local > 1 else '', remote, 's' if remote > 1 else '', )) elif local: print indent + style('%s %s ahead%s by %d commit%s%s' % ( local_name, local_verb, ' of ' + remote_name if remote_name else '', local, 's' if local > 1 else '', '; ' + ahead_action if ahead_action else '.', ), fg='green', reset=True) elif remote: print indent + style_warning('%s %s behind%s by %d commit%s%s' % ( local_name, local_verb, ' ' + remote_name if remote_name else '', remote, 's' if remote > 1 else '', '; ' + behind_action if behind_action else '.', ))
def update(self, force=False): log.info(style_note('Updating repo', self.name)) self.clone_if_not_exists() if self.remote_name not in self.remotes(): log.warning( style_warning('"%s" does not have remote "%s"' % (self.name, self.remote_name))) return True rev = self.fetch() if not force and not self.check_ff_safety(rev): log.error('Cannot fast-forward; skipping.') return False self.checkout(force=force) return True
def upgrade(self, dirty=False, subset=None, reinstall=False, relink=False, no_deps=False, force_branch_link=True): self.clone_if_not_exists() try: head = self.head except CalledProcessError: log.warning(style_warning('no commits in repository')) head = None try: remote_head = self.rev_parse('%s/%s' % (self.remote_name, self.branch_name)) except ValueError: log.warning( style_warning('tracked %s/%s does not exist in self' % (self.remote_name, self.branch_name))) remote_head = None if remote_head and head != remote_head: log.warning( style_warning('%s repo not checked out to %s/%s' % (self.name, self.remote_name, self.branch_name))) dirty = bool(list(self.status())) if not dirty and self.is_dirty(): log.error('%s repo is dirty; force with --dirty' % self.name) return False env = self.get_environment() req_set = self.load_requirements() pkg_set = PackageSet(env=env, home=self.home) # Register the whole set, so that dependencies are pulled from here instead # of weakly resolved from installed packages. # TODO: This blanket reinstalls things, even if no_deps is set. pkg_set.resolve_set(req_set, check_existing=not reinstall) # Install and/or link. pkg_set.install(subset or None, link_env=env, reinstall=reinstall, relink=relink, no_deps=no_deps) if pkg_set._errored and not force_branch_link: log.warning( style_warning( "Not creating branch or version links; force with --force-branch-link" )) return False # Create a symlink by branch. path_by_branch = self.home._abs_path('environments', self.name, self.branch_name) if os.path.lexists(path_by_branch): os.unlink(path_by_branch) makedirs(os.path.dirname(path_by_branch)) os.symlink(env.path, path_by_branch) # Create a symlink by version. version = req_set.headers.get('Version') if version: path_by_version = self.home._abs_path( 'environments', self.name, 'versions', version.value + ('-dirty' if dirty else '')) if os.path.lexists(path_by_version): os.unlink(path_by_version) makedirs(os.path.dirname(path_by_version)) os.symlink(env.path, path_by_version) return True
def doctor(args): """Perform self-checks to make sure VEE is OK.""" if args.ping: print 'pong' return import vee.__about__ as about if args.version: print about.__version__ + ('+' + about.__revision__ if args.revision else '') return if args.revision: print about.__revision__ return print style_note('==> VEE') print style_note('version:', about.__version__) print style_note('revision:', about.__revision__) print style_note('package:', os.path.abspath(os.path.join(__file__, '..', '..'))) res = 0 def find_command(name, warn=False): path = which(name) if path: print style_note('%s:' % name, path) else: if warn: print style_warning('cannot find %s' % name) else: print style_error('cannot find %s' % name) return 1 print style_note('==> dependencies') for name, expected_version, in [('setuptools', '18.0.1'), ('virtualenv', '13.1.0')]: module = globals()[name] actual_version = module.__version__ if expected_version == actual_version: print style_note(name + ':', expected_version) else: print style( '%s: %s (expected vendored %s) from %s' % (name, actual_version, expected_version, module.__file__), 'yellow') res = 2 print style_note('==> executables') print style_note('python:', sys.executable) res = find_command('git') or res if sys.platform == 'darwin': res = find_command('install_name_tool') or res if sys.platform.startswith('linux'): res = find_command('patchelf', warn=True) or res print style_note('==> configuration') home = args.assert_home() print style_note('home:', home.root) try: repo = home.get_env_repo() except ValueError: print style_warning('no default repo.', 'Use `vee repo add --default URL`.') return print style_note('repo:', repo.name, repo.remote_url) print style_note('==> summary') if not res: print style('Everything looks OK', 'green') else: print style('Something may be wrong', 'yellow') return res
def status(args): home = args.assert_home() env_repo = home.get_env_repo(args.repo) pkg_set = PackageSet(home=home) by_name = {} # Dev packages. for row in home.db.execute('SELECT * FROM development_packages'): row = dict(row) if not os.path.exists(row['path']): continue dev_repo = GitRepo(row['path']) row['remotes'] = dev_repo.remotes() by_name.setdefault(row['name'], {})['dev'] = row # Current requirements. for revision, name in [ (None, 'work'), ('HEAD', 'head'), ]: for req in env_repo.load_requirements( revision=revision).iter_packages(): pkg = pkg_set.resolve(req, check_existing=False) if pkg.fetch_type != 'git': continue by_name.setdefault(pkg.name, {})[name] = req by_name = by_name.items() by_name.sort(key=lambda x: x[0].lower()) if args.names: by_name = [x for x in by_name if x[0] in args.names] for name, everything in by_name: dev_row = everything.get('dev') work_req = everything.get('work') head_req = everything.get('head') has_dev = dev_row is not None only_has_dev = has_dev and not (work_req or head_req) # Skip dev-only stuff most of the time. if only_has_dev and not args.all_dev: continue # Title. print '%s %s' % (style( '%s %s' % ('==>' if has_dev else '-->', name), fg='blue'), '(dev only)' if only_has_dev else '') # Status of requirements. if work_req and head_req and str(work_req) == str(head_req): if args.verbose: print '=== %s' % work_req else: # Print a lovely coloured diff of the specific arguments that # are changing. # TODO: make this environment relative to the context. head_args = head_req.to_args( exclude=('base_environ', )) if head_req else [] work_args = work_req.to_args( exclude=('base_environ', )) if work_req else [] differ = difflib.SequenceMatcher(None, head_args, work_args) opcodes = differ.get_opcodes() if head_req is not None: print style('---', fg='red', bold=True), for tag, i1, i2, j1, j2 in opcodes: if tag in ('replace', 'delete'): print style(' '.join(head_args[i1:i2]), fg='red', bold=True) elif tag in ('equal', ): print ' '.join(head_args[i1:i2]), if work_req is not None: print style('+++', fg='green', bold=True), for tag, i1, i2, j1, j2 in opcodes: if tag in ('replace', 'insert'): print style(' '.join(work_args[j1:j2]), fg='green', bold=True) elif tag in ('equal', ): print ' '.join(work_args[j1:j2]), if dev_row: if 'warning' in dev_row: print dev_row['warning'] if 'origin' in dev_row['remotes']: dev_row['remote_name'] = 'origin' else: remote_names = sorted(dev_row['remotes']) dev_row['remote_name'] = remote_names[0] if len(remote_names) != 1: print ' ' + style_warning( 'More that one non-origin remote; picking %s' % dev_row['remote_name']) dev_repo = dev_row and GitRepo(dev_row['path']) if dev_repo and not dev_repo.exists: print style_warning('Git repo does not exist.') dev_row = dev_repo = None if dev_repo: if dev_repo.status(): print ' ' + style_warning('Work tree is dirty.') if args.fetch: dev_remote_head = dev_repo.fetch(dev_row['remote_name'], 'master') else: dev_remote_head = dev_repo.rev_parse(dev_row['remote_name'] + '/master') # Check your local dev vs. its remote. dev_local, dev_remote = dev_repo.distance(dev_repo.head, dev_remote_head) summarize_rev_distance( dev_local, dev_remote, local_name=name, local_verb='is', remote_name='%s/master' % dev_row['remote_name'], behind_action='please pull or `vee dev ff %s`' % name, ) if dev_repo and work_req and work_req.revision: # Check your local dev vs the required revision try: pkg_revision = dev_repo.rev_parse(work_req.revision) pkg_local, pkg_remote = dev_repo.distance( dev_repo.head, pkg_revision) summarize_rev_distance( pkg_local, pkg_remote, local_name=name, local_verb='is', remote_name='%s repo' % env_repo.name, ahead_action='you may `vee add %s`' % name, behind_action='please `vee dev checkout --repo %s %s`' % (env_repo.name, name), ) except Exception as e: print ' ' + format_cli_exc(e)