Beispiel #1
0
class Worker:
    """The worker Class."""

    def __init__(self, args):
        """Constructor."""
        self.args = args
        self.git = Git(args)

    def branches_to_be_deleted(self):
        """Return branches to be deleted."""
        branches = self.branches_to_be_deleted_excluding_skipped()
        if len(branches) > 0:
            Formatter.print_pretty_warn_message("Following local branches would \
                be deleted:")
            return branches
        else:
            Formatter.print_pretty_fail_message("No branches to be deleted")
            return []

    def branches_to_be_deleted_excluding_skipped(self):
        """Return branches to be deleted except pattern matching branches."""
        branches = list(
            set(
                self.git.merged_branches()
            ).difference(
                self.git.pattern_matching_branches())
            )
        self.exclude_current_branch(branches)
        return branches

    def delete_branches(self, remote=False):
        """Delete the branches."""
        """If Remote=True, deletes remote branches as well."""
        if len(self.branches_to_be_deleted()) > 0:
            self.delete_local_branches()
            if remote:
                self.delete_remote_branches()
            Formatter.print_pretty_ok_message("Cleaned Successfully!!")

    def delete_remote_branches(self):
        """Delete remote branches."""
        try:
            os.popen("git push origin --delete " + " ".join(
                self.branches_to_be_deleted())
            )
        except:
            print "There was an error deleting remote branches: ",
            sys.exc_info()[0]

    def delete_local_branches(self):
        """Delete local branches."""
        os.popen("git branch -D " + " ".join(self.branches_to_be_deleted()))

    def exclude_current_branch(self, branches):
        """Exclude current branch from list of branches to be deleted."""
        if(self.git.current_branch() in branches):
            branches.remove(self.git.current_branch())
Beispiel #2
0
class Worker:
    """The worker Class."""
    def __init__(self, args):
        """Constructor."""
        self.args = args
        self.git = Git(args)

    def branches_to_be_deleted(self):
        """Return branches to be deleted."""
        branches = self.branches_to_be_deleted_excluding_skipped()
        if len(branches) > 0:
            Formatter.print_pretty_warn_message(
                "Following local branches would \
                be deleted:")
            return branches
        else:
            Formatter.print_pretty_fail_message("No branches to be deleted")
            return []

    def branches_to_be_deleted_excluding_skipped(self):
        """Return branches to be deleted except pattern matching branches."""
        branches = list(
            set(self.git.merged_branches()).difference(
                self.git.pattern_matching_branches()))
        self.exclude_current_branch(branches)
        return branches

    def delete_branches(self, remote=False):
        """Delete the branches."""
        """If Remote=True, deletes remote branches as well."""
        if len(self.branches_to_be_deleted()) > 0:
            self.delete_local_branches()
            if remote:
                self.delete_remote_branches()
            Formatter.print_pretty_ok_message("Cleaned Successfully!!")

    def delete_remote_branches(self):
        """Delete remote branches."""
        try:
            os.popen("git push origin --delete " +
                     " ".join(self.branches_to_be_deleted()))
        except:
            print "There was an error deleting remote branches: ",
            sys.exc_info()[0]

    def delete_local_branches(self):
        """Delete local branches."""
        os.popen("git branch -D " + " ".join(self.branches_to_be_deleted()))

    def exclude_current_branch(self, branches):
        """Exclude current branch from list of branches to be deleted."""
        if (self.git.current_branch() in branches):
            branches.remove(self.git.current_branch())
Beispiel #3
0
def regenerate_includes(work_dir: Path, config: ImportConfig) -> None:
    for ledger_config in config.ledgers.values():
        if work_dir.is_relative_to(ledger_config.ledger_dir):
            break
    else:
        print(f'Current working directory {work_dir} is not inside any known'
              ' ledger path.')
        exit(1)

    print(f'Regenerate includes in {ledger_config.ledger_dir}.')
    # change working directory for git status to work correctly
    os.chdir(ledger_config.ledger_dir)
    git: BaseGit
    if ledger_config.git_dir is not None:
        git = Git(ledger_config.ledger_dir, ledger_config.git_dir)
        import_branch = ledger_config.import_branch
    else:
        git = FakeGit()
        import_branch = git.current_branch()

    write_include_files(ledger_config.ledger_dir, git)
Beispiel #4
0
class Project():
	def __init__(self):
		self.tree = ElementTree();
		self.git = Git()
		if not os.path.exists(PROJECT_CONFIG_PATH):
			os.mkdir(PROJECT_CONFIG_PATH)
		try:
			self.tree.parse(PROJECT_CONFIG_FILE)
		except:
			root = Element('Project', {'name':os.path.basename(os.getcwd())})
			self.tree._setroot(root)

	def save(self):
		self.tree.write(PROJECT_CONFIG_FILE, xml_declaration=True, method="xml")

	def iter(self):
		return self.tree.iter('SubProject')

	def find(self, name):
		for i in self.iter():
			if i.get('name') == name:
				return i

	def inSubProject(self):
		cwd = os.getcwd()
		for node in self.iter():
			name = node.get('name')
			print("")
			print("On:%s" % name)
			print("***************************************")
			os.chdir("/".join([cwd, name]))
			yield
			print("***************************************")

	def clone(self):
		for module in self.iter():
			self.git.clone(module)

	def __init_module(self, module):
		if not os.path.exists(module):
			print("module %s not exists." % module)
			return None
		cwd = os.getcwd()
		os.chdir("/".join([cwd, module]))
		if self.git.is_repo():
			node = Element('SubProject')
			node.set("name", module)
			current_branch = self.git.current_branch()
			if current_branch != None:
				node.set("branch", current_branch)
			remote_uri = self.git.current_remote_uri(branch=current_branch)
			if remote_uri != None:
				node.set("uri", remote_uri)
			else:
				node = None
		else:
			print("fatal: Not a git repository")
			node = None
				
		os.chdir(cwd)
		return node

	def __append_ignore_file(self, module):
		if os.path.exists(".gitignore"):
			ignoreFile = open(".gitignore","r")
			for line in ignoreFile:
				if module == line.strip():
					return
			ignoreFile.close()
		ignoreFile = open(".gitignore", "a")
		ignoreFile.write(module + "\n")
		ignoreFile.close()

	def __remove_ignore_file(self, modules):
		if os.path.exists(".gitignore"):
			ignoreFile = open(".gitignore","r")
			print modules
			data = [line.strip() for line in ignoreFile if not (line.strip() in modules)]
			ignoreFile = open(".gitignore", "w")
			ignoreFile.write("\n".join(data)+"\n")
			ignoreFile.close()
			data = None


	def append(self, module):
		if module == None:
			return -1
		node = self.find(module)
		root = self.tree.getroot()
		if node != None:
			root.remove(node)
		node = self.__init_module(module)
		if node == None:
			return -1
		else:
			root.append(node)
			self.__append_ignore_file(module)
		self.save()
		return 0

	def remove(self, module=None):
		if module != None:
			node = self.find(module)
			root = self.tree.getroot()
			if node != None:
				root.remove(node)
				self.__remove_ignore_file(module)
				self.save()
		else:
			data = [node.get('name') for node in self.iter()]
			self.__remove_ignore_file(data)
Beispiel #5
0
def main() -> None:
    aparser = argparse.ArgumentParser(
            description='import account statement PDFs into hledger')
    aparser.add_argument('--force', dest='force', default=False,
                         action='store_true',
                         help='overwrite existing ledgers')
    aparser.add_argument('--dry-run', dest='dry_run',
                         default=False, action='store_true',
                         help='run parsers without writing any output files')
    aparser.add_argument('--regenerate-includes', dest='regenerate_includes',
                         default=False, action='store_true',
                         help='only regenerate include files; don\'t import '
                              'new bank statements')
    aparser.add_argument('--no-merge', dest='merge',
                         default=True, action='store_false',
                         help='don\'t merge import branch after import')

    args = aparser.parse_args()

    xdg = getXDGdirectories('bank-statement-parser')
    config_file = xdg['config'] / 'import.cfg'
    config = ImportConfig.read_from_file(config_file)

    if args.regenerate_includes:
        regenerate_includes(Path.cwd(), config)
        exit(0)

    selection_script = xdg['config'] / 'select_ledger.py'
    select_ledger: Callable[[BankStatementMetadata], str]
    if selection_script.exists():
        with open(selection_script, 'r') as f:
            content = f.read()
            parse_globals: dict[str, Any] = {
                'BankStatementMetadata': BankStatementMetadata,
                }
            exec(compile(content, selection_script, 'exec'), parse_globals)
            if 'select_ledger' not in parse_globals:
                print(f'{selection_script} doesn\'t contain select_ledger'
                      ' function.',
                      file=sys.stderr)
                exit(1)
            select_ledger = parse_globals['select_ledger']
    elif len(config.ledgers) == 1:
        ledger_name = next(iter(config.ledgers))
        def select_ledger(meta: BankStatementMetadata) -> str:
            return ledger_name
    else:
        print(f'Error: {config_file} contains more than one ledger,'
              f' but {selection_script} is missing.',
              file=sys.stderr)
        exit(1)
    incoming_statements = get_metadata_of_incoming_statements(
            config.incoming_dir)
    classified = sort_incoming_statements_to_ledger_dirs(
            incoming_statements,
            select_ledger,
            )
    if any(key not in config.ledgers for key in classified.keys()):
        for key, statements in classified.items():
            if key in config.ledgers:
                continue
            mismatched_files = ', '.join(str(s.statement_path)
                                         for s in statements)
            print(f'Error: {mismatched_files} were assigned to unknown ledger'
                  f' configuration {key}. Please check {selection_script}.',
                  file=sys.stderr)
        exit(1)
    for key, statements in classified.items():
        ledger_config = config.ledgers[key]
        print(f'Importing bank statements to {ledger_config.ledger_dir}.')
        # change working directory for git status to work correctly
        os.chdir(ledger_config.ledger_dir)
        git: BaseGit
        if ledger_config.git_dir is not None:
            git = Git(ledger_config.ledger_dir, ledger_config.git_dir)
            import_branch = ledger_config.import_branch
        else:
            git = FakeGit()
            import_branch = git.current_branch()

        try:
            import_incoming_statements(statements,
                                       ledger_config.ledger_dir,
                                       git, import_branch,
                                       args.force, args.dry_run)
        except DirtyWorkingDirectoryException:
            print(f'{ledger_config.ledger_dir} contains uncommitted changes,'
                  ' please commit those before continuing.', file=sys.stderr)
            exit(1)
        # The import_transaction in import_incoming_statements automatically
        # resets the branch to the previously checked-out one after importing
        # to the import_branch.
        if (args.merge
                and isinstance(git, Git)
                and import_branch != git.current_branch()):
            try:
                git.merge(import_branch)
            except GitMergeConflictError as e:
                conflicting_files = [ledger_config.ledger_dir / c.name
                                     for c in e.conflicts]
                not_autogenerated = [p for p in conflicting_files
                                     if p.name != 'journal.hledger']
                if not_autogenerated:
                    raise RuntimeError(
                            'Could not automerge the following files:\n'
                            + '\n'.join(str(p) for p in not_autogenerated))
                write_include_files(ledger_config.ledger_dir, git)
                git.commit(f"Merge branch '{import_branch}'")