gitbetter.gitbetter

  1import os
  2
  3from argshell import ArgShell, ArgShellParser, Namespace, with_parser
  4from pathier import Pathier
  5
  6from gitbetter import git
  7
  8
  9def new_remote_parser() -> ArgShellParser:
 10    parser = ArgShellParser()
 11    parser.add_argument(
 12        "--public",
 13        action="store_true",
 14        help=""" Set the new remote visibility as public. Defaults to private. """,
 15    )
 16    return parser
 17
 18
 19def commit_files_parser() -> ArgShellParser:
 20    parser = ArgShellParser()
 21    parser.add_argument(
 22        "files", type=str, nargs="*", help=""" List of files to stage and commit. """
 23    )
 24    parser.add_argument(
 25        "-m",
 26        "--message",
 27        type=str,
 28        required=True,
 29        help=""" The commit message to use. """,
 30    )
 31    parser.add_argument(
 32        "-r",
 33        "--recursive",
 34        action="store_true",
 35        help=""" If a file name is not found in the current working directory,
 36        search for it in subfolders. This avoids having to type paths to files in subfolders,
 37        but if you have multiple files in different subfolders with the same name that have changes they
 38        will all be staged and committed.""",
 39    )
 40    return parser
 41
 42
 43def amend_files_parser() -> ArgShellParser:
 44    parser = ArgShellParser()
 45    parser.add_argument(
 46        "-f",
 47        "--files",
 48        type=str,
 49        nargs="*",
 50        help=""" List of files to stage and commit. """,
 51    )
 52    parser.add_argument(
 53        "-r",
 54        "--recursive",
 55        action="store_true",
 56        help=""" If a file name is not found in the current working directory,
 57        search for it in subfolders. This avoids having to type paths to files in subfolders,
 58        but if you have multiple files in different subfolders with the same name that have changes they
 59        will all be staged and committed.""",
 60    )
 61    return parser
 62
 63
 64def delete_branch_parser() -> ArgShellParser:
 65    parser = ArgShellParser()
 66    parser.add_argument(
 67        "branch", type=str, help=""" The name of the branch to delete. """
 68    )
 69    parser.add_argument(
 70        "-r",
 71        "--remote",
 72        action="store_true",
 73        help=""" Delete the remote and remote-tracking branches along with the local branch.
 74        By default only the local branch is deleted.""",
 75    )
 76    return parser
 77
 78
 79def recurse_files(filenames: list[str]) -> list[str]:
 80    files = []
 81    for filename in filenames:
 82        if not Pathier(filename).exists():
 83            results = list(Pathier.cwd().rglob(f"{filename}"))
 84            if not results:
 85                print(f"WARNING: Could not find any files with name {filename}")
 86            else:
 87                files.extend([str(result) for result in results])
 88        else:
 89            files.append(filename)
 90    return files
 91
 92
 93def files_postparser(args: Namespace) -> Namespace:
 94    if args.recursive:
 95        args.files = recurse_files(args.files)
 96    return args
 97
 98
 99class GitBetter(ArgShell):
100    """GitBetter Shell."""
101
102    intro = "Starting gitbetter...\nEnter 'help' or '?' for command help."
103    prompt = f"gitbetter::{Pathier.cwd()}>"
104    execute_in_terminal_if_unrecognized = True
105
106    def default(self, line: str):
107        if self.execute_in_terminal_if_unrecognized:
108            os.system(line)
109        else:
110            super().default(line)
111
112    def do_help(self, arg: str):
113        """List available commands with "help" or detailed help with "help cmd"."""
114        super().do_help(arg)
115        if not arg:
116            print(self.unrecognized_command_behavior_status)
117            if self.execute_in_terminal_if_unrecognized:
118                print(
119                    "^Essentially makes this shell function as a super-shell of whatever shell you launched gitbetter from.^"
120                )
121        print()
122
123    @property
124    def unrecognized_command_behavior_status(self):
125        return f"Unrecognized command behavior: {'Execute with os.system()' if self.execute_in_terminal_if_unrecognized else 'Print unknown syntax error'}"
126
127    def do_toggle_unrecognized_command_behavior(self, arg: str):
128        """Toggle whether the shell will attempt to execute unrecognized commands as system commands in the terminal.
129        When on (the default), `GitBetter` will treat unrecognized commands as if you added the `sys` command in front of the input, i.e. `os.system(your_input)`.
130        When off, an `unknown syntax` message will be printed and no commands will be executed."""
131        self.execute_in_terminal_if_unrecognized = (
132            not self.execute_in_terminal_if_unrecognized
133        )
134        print(self.unrecognized_command_behavior_status)
135
136    def do_cd(self, path: str):
137        """Change current working directory to `path`."""
138        os.chdir(path)
139        self.prompt = f"gitbetter::{Pathier.cwd()}>"
140
141    def do_git(self, arg: str):
142        """Directly execute `git {arg}`.
143
144        i.e. You can still do everything directly invoking git can do."""
145        git.execute(arg)
146
147    def do_new_repo(self, _: str):
148        """Create a new git repo in this directory."""
149        git.new_repo()
150
151    def do_new_branch(self, name: str):
152        """Create and switch to a new branch named after the supplied arg."""
153        git.create_new_branch(name)
154
155    @with_parser(new_remote_parser)
156    def do_new_gh_remote(self, args: Namespace):
157        """Create a remote GitHub repository for this repo.
158
159        GitHub CLI must be installed and configured for this to work."""
160        name = Pathier.cwd().stem
161        git.create_remote(name, args.public)
162
163    def do_initcommit(self, _: str):
164        """Stage and commit all files with message "Initial Commit"."""
165        git.initcommit()
166
167    def do_undo(self, _: str):
168        """Undo all uncommitted changes."""
169        git.undo()
170
171    @with_parser(amend_files_parser, [files_postparser])
172    def do_add(self, args: Namespace):
173        """Stage a list of files.
174        If no files are given, all files will be added."""
175        git.add(None if not args.files else args.files)
176
177    def do_commit(self, message: str):
178        """Commit staged files with this message."""
179        if not message.startswith('"'):
180            message = '"' + message
181        if not message.endswith('"'):
182            message += '"'
183        git.commit(f"-m {message}")
184
185    @with_parser(commit_files_parser, [files_postparser])
186    def do_commitf(self, args: Namespace):
187        """Stage and commit a list of files."""
188        git.commit_files(args.files, args.message)
189
190    def do_commitall(self, message: str):
191        """Stage and commit all files with this message."""
192        if not message.startswith('"'):
193            message = '"' + message
194        if not message.endswith('"'):
195            message += '"'
196        git.add()
197        git.commit(f"-m {message}")
198
199    def do_switch(self, branch_name: str):
200        """Switch to this branch."""
201        git.switch_branch(branch_name)
202
203    def do_add_url(self, url: str):
204        """Add remote url for repo and push repo."""
205        git.add_remote_url(url)
206        git.push("-u origin main")
207
208    def do_push_new(self, branch_name: str):
209        """Push this new branch to origin with -u flag."""
210        git.push_new_branch(branch_name)
211
212    def do_push(self, args: str):
213        """Execute `git push`.
214
215        `args` can be any additional args that `git push` accepts."""
216        git.push(args)
217
218    def do_pull(self, args: str):
219        """Execute `git pull`.
220
221        `args` can be any additional args that `git pull` accepts."""
222        git.pull(args)
223
224    def do_list_branches(self, _: str):
225        """Show local and remote branches."""
226        git.list_branches()
227
228    def do_loggy(self, _: str):
229        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
230        git.loggy()
231
232    def do_merge(self, branch_name: str):
233        """Merge supplied `branch_name` with the currently active branch."""
234        git.merge(branch_name)
235
236    def do_tag(self, tag_id: str):
237        """Tag current commit with `tag_id`."""
238        git.tag(tag_id)
239
240    @with_parser(amend_files_parser, [files_postparser])
241    def do_amend(self, args: Namespace):
242        """Stage files and add to previous commit."""
243        git.amend(args.files)
244
245    @with_parser(delete_branch_parser)
246    def do_delete_branch(self, args: Namespace):
247        """Delete branch."""
248        git.delete_branch(args.branch, not args.remote)
249
250    def do_pull_branch(self, branch: str):
251        """Pull this branch from the origin."""
252        git.pull_branch(branch)
253
254    def do_ignore(self, patterns: str):
255        """Add the list of patterns to `.gitignore`."""
256        patterns = "\n".join(patterns.split())
257        path = Pathier(".gitignore")
258        path.append("\n")
259        path.append(patterns, False)
260
261    def do_make_private(self, owner: str):
262        """Make the GitHub remote for this repo private.
263
264        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
265
266        This repo must exist and GitHub CLI must be installed and configured."""
267        git.make_private(owner, Pathier.cwd().stem)
268
269    def do_make_public(self, owner: str):
270        """Make the GitHub remote for this repo public.
271
272        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
273
274        This repo must exist and GitHub CLI must be installed and configured."""
275        git.make_public(owner, Pathier.cwd().stem)
276
277    def do_delete_gh_repo(self, owner: str):
278        """Delete this repo from GitHub.
279
280        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
281
282        GitHub CLI must be installed and configured.
283
284        May require you to reauthorize and rerun command."""
285        git.delete_remote(owner, Pathier.cwd().stem)
286
287
288def main():
289    GitBetter().cmdloop()
290
291
292if __name__ == "__main__":
293    main()
def new_remote_parser() -> argshell.argshell.ArgShellParser:
10def new_remote_parser() -> ArgShellParser:
11    parser = ArgShellParser()
12    parser.add_argument(
13        "--public",
14        action="store_true",
15        help=""" Set the new remote visibility as public. Defaults to private. """,
16    )
17    return parser
def commit_files_parser() -> argshell.argshell.ArgShellParser:
20def commit_files_parser() -> ArgShellParser:
21    parser = ArgShellParser()
22    parser.add_argument(
23        "files", type=str, nargs="*", help=""" List of files to stage and commit. """
24    )
25    parser.add_argument(
26        "-m",
27        "--message",
28        type=str,
29        required=True,
30        help=""" The commit message to use. """,
31    )
32    parser.add_argument(
33        "-r",
34        "--recursive",
35        action="store_true",
36        help=""" If a file name is not found in the current working directory,
37        search for it in subfolders. This avoids having to type paths to files in subfolders,
38        but if you have multiple files in different subfolders with the same name that have changes they
39        will all be staged and committed.""",
40    )
41    return parser
def amend_files_parser() -> argshell.argshell.ArgShellParser:
44def amend_files_parser() -> ArgShellParser:
45    parser = ArgShellParser()
46    parser.add_argument(
47        "-f",
48        "--files",
49        type=str,
50        nargs="*",
51        help=""" List of files to stage and commit. """,
52    )
53    parser.add_argument(
54        "-r",
55        "--recursive",
56        action="store_true",
57        help=""" If a file name is not found in the current working directory,
58        search for it in subfolders. This avoids having to type paths to files in subfolders,
59        but if you have multiple files in different subfolders with the same name that have changes they
60        will all be staged and committed.""",
61    )
62    return parser
def delete_branch_parser() -> argshell.argshell.ArgShellParser:
65def delete_branch_parser() -> ArgShellParser:
66    parser = ArgShellParser()
67    parser.add_argument(
68        "branch", type=str, help=""" The name of the branch to delete. """
69    )
70    parser.add_argument(
71        "-r",
72        "--remote",
73        action="store_true",
74        help=""" Delete the remote and remote-tracking branches along with the local branch.
75        By default only the local branch is deleted.""",
76    )
77    return parser
def recurse_files(filenames: list[str]) -> list[str]:
80def recurse_files(filenames: list[str]) -> list[str]:
81    files = []
82    for filename in filenames:
83        if not Pathier(filename).exists():
84            results = list(Pathier.cwd().rglob(f"{filename}"))
85            if not results:
86                print(f"WARNING: Could not find any files with name {filename}")
87            else:
88                files.extend([str(result) for result in results])
89        else:
90            files.append(filename)
91    return files
def files_postparser(args: argshell.argshell.Namespace) -> argshell.argshell.Namespace:
94def files_postparser(args: Namespace) -> Namespace:
95    if args.recursive:
96        args.files = recurse_files(args.files)
97    return args
class GitBetter(argshell.argshell.ArgShell):
100class GitBetter(ArgShell):
101    """GitBetter Shell."""
102
103    intro = "Starting gitbetter...\nEnter 'help' or '?' for command help."
104    prompt = f"gitbetter::{Pathier.cwd()}>"
105    execute_in_terminal_if_unrecognized = True
106
107    def default(self, line: str):
108        if self.execute_in_terminal_if_unrecognized:
109            os.system(line)
110        else:
111            super().default(line)
112
113    def do_help(self, arg: str):
114        """List available commands with "help" or detailed help with "help cmd"."""
115        super().do_help(arg)
116        if not arg:
117            print(self.unrecognized_command_behavior_status)
118            if self.execute_in_terminal_if_unrecognized:
119                print(
120                    "^Essentially makes this shell function as a super-shell of whatever shell you launched gitbetter from.^"
121                )
122        print()
123
124    @property
125    def unrecognized_command_behavior_status(self):
126        return f"Unrecognized command behavior: {'Execute with os.system()' if self.execute_in_terminal_if_unrecognized else 'Print unknown syntax error'}"
127
128    def do_toggle_unrecognized_command_behavior(self, arg: str):
129        """Toggle whether the shell will attempt to execute unrecognized commands as system commands in the terminal.
130        When on (the default), `GitBetter` will treat unrecognized commands as if you added the `sys` command in front of the input, i.e. `os.system(your_input)`.
131        When off, an `unknown syntax` message will be printed and no commands will be executed."""
132        self.execute_in_terminal_if_unrecognized = (
133            not self.execute_in_terminal_if_unrecognized
134        )
135        print(self.unrecognized_command_behavior_status)
136
137    def do_cd(self, path: str):
138        """Change current working directory to `path`."""
139        os.chdir(path)
140        self.prompt = f"gitbetter::{Pathier.cwd()}>"
141
142    def do_git(self, arg: str):
143        """Directly execute `git {arg}`.
144
145        i.e. You can still do everything directly invoking git can do."""
146        git.execute(arg)
147
148    def do_new_repo(self, _: str):
149        """Create a new git repo in this directory."""
150        git.new_repo()
151
152    def do_new_branch(self, name: str):
153        """Create and switch to a new branch named after the supplied arg."""
154        git.create_new_branch(name)
155
156    @with_parser(new_remote_parser)
157    def do_new_gh_remote(self, args: Namespace):
158        """Create a remote GitHub repository for this repo.
159
160        GitHub CLI must be installed and configured for this to work."""
161        name = Pathier.cwd().stem
162        git.create_remote(name, args.public)
163
164    def do_initcommit(self, _: str):
165        """Stage and commit all files with message "Initial Commit"."""
166        git.initcommit()
167
168    def do_undo(self, _: str):
169        """Undo all uncommitted changes."""
170        git.undo()
171
172    @with_parser(amend_files_parser, [files_postparser])
173    def do_add(self, args: Namespace):
174        """Stage a list of files.
175        If no files are given, all files will be added."""
176        git.add(None if not args.files else args.files)
177
178    def do_commit(self, message: str):
179        """Commit staged files with this message."""
180        if not message.startswith('"'):
181            message = '"' + message
182        if not message.endswith('"'):
183            message += '"'
184        git.commit(f"-m {message}")
185
186    @with_parser(commit_files_parser, [files_postparser])
187    def do_commitf(self, args: Namespace):
188        """Stage and commit a list of files."""
189        git.commit_files(args.files, args.message)
190
191    def do_commitall(self, message: str):
192        """Stage and commit all files with this message."""
193        if not message.startswith('"'):
194            message = '"' + message
195        if not message.endswith('"'):
196            message += '"'
197        git.add()
198        git.commit(f"-m {message}")
199
200    def do_switch(self, branch_name: str):
201        """Switch to this branch."""
202        git.switch_branch(branch_name)
203
204    def do_add_url(self, url: str):
205        """Add remote url for repo and push repo."""
206        git.add_remote_url(url)
207        git.push("-u origin main")
208
209    def do_push_new(self, branch_name: str):
210        """Push this new branch to origin with -u flag."""
211        git.push_new_branch(branch_name)
212
213    def do_push(self, args: str):
214        """Execute `git push`.
215
216        `args` can be any additional args that `git push` accepts."""
217        git.push(args)
218
219    def do_pull(self, args: str):
220        """Execute `git pull`.
221
222        `args` can be any additional args that `git pull` accepts."""
223        git.pull(args)
224
225    def do_list_branches(self, _: str):
226        """Show local and remote branches."""
227        git.list_branches()
228
229    def do_loggy(self, _: str):
230        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
231        git.loggy()
232
233    def do_merge(self, branch_name: str):
234        """Merge supplied `branch_name` with the currently active branch."""
235        git.merge(branch_name)
236
237    def do_tag(self, tag_id: str):
238        """Tag current commit with `tag_id`."""
239        git.tag(tag_id)
240
241    @with_parser(amend_files_parser, [files_postparser])
242    def do_amend(self, args: Namespace):
243        """Stage files and add to previous commit."""
244        git.amend(args.files)
245
246    @with_parser(delete_branch_parser)
247    def do_delete_branch(self, args: Namespace):
248        """Delete branch."""
249        git.delete_branch(args.branch, not args.remote)
250
251    def do_pull_branch(self, branch: str):
252        """Pull this branch from the origin."""
253        git.pull_branch(branch)
254
255    def do_ignore(self, patterns: str):
256        """Add the list of patterns to `.gitignore`."""
257        patterns = "\n".join(patterns.split())
258        path = Pathier(".gitignore")
259        path.append("\n")
260        path.append(patterns, False)
261
262    def do_make_private(self, owner: str):
263        """Make the GitHub remote for this repo private.
264
265        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
266
267        This repo must exist and GitHub CLI must be installed and configured."""
268        git.make_private(owner, Pathier.cwd().stem)
269
270    def do_make_public(self, owner: str):
271        """Make the GitHub remote for this repo public.
272
273        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
274
275        This repo must exist and GitHub CLI must be installed and configured."""
276        git.make_public(owner, Pathier.cwd().stem)
277
278    def do_delete_gh_repo(self, owner: str):
279        """Delete this repo from GitHub.
280
281        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
282
283        GitHub CLI must be installed and configured.
284
285        May require you to reauthorize and rerun command."""
286        git.delete_remote(owner, Pathier.cwd().stem)

GitBetter Shell.

def default(self, line: str):
107    def default(self, line: str):
108        if self.execute_in_terminal_if_unrecognized:
109            os.system(line)
110        else:
111            super().default(line)

Called on an input line when the command prefix is not recognized.

If this method is not overridden, it prints an error message and returns.

def do_help(self, arg: str):
113    def do_help(self, arg: str):
114        """List available commands with "help" or detailed help with "help cmd"."""
115        super().do_help(arg)
116        if not arg:
117            print(self.unrecognized_command_behavior_status)
118            if self.execute_in_terminal_if_unrecognized:
119                print(
120                    "^Essentially makes this shell function as a super-shell of whatever shell you launched gitbetter from.^"
121                )
122        print()

List available commands with "help" or detailed help with "help cmd".

def do_toggle_unrecognized_command_behavior(self, arg: str):
128    def do_toggle_unrecognized_command_behavior(self, arg: str):
129        """Toggle whether the shell will attempt to execute unrecognized commands as system commands in the terminal.
130        When on (the default), `GitBetter` will treat unrecognized commands as if you added the `sys` command in front of the input, i.e. `os.system(your_input)`.
131        When off, an `unknown syntax` message will be printed and no commands will be executed."""
132        self.execute_in_terminal_if_unrecognized = (
133            not self.execute_in_terminal_if_unrecognized
134        )
135        print(self.unrecognized_command_behavior_status)

Toggle whether the shell will attempt to execute unrecognized commands as system commands in the terminal. When on (the default), GitBetter will treat unrecognized commands as if you added the sys command in front of the input, i.e. os.system(your_input). When off, an unknown syntax message will be printed and no commands will be executed.

def do_cd(self, path: str):
137    def do_cd(self, path: str):
138        """Change current working directory to `path`."""
139        os.chdir(path)
140        self.prompt = f"gitbetter::{Pathier.cwd()}>"

Change current working directory to path.

def do_git(self, arg: str):
142    def do_git(self, arg: str):
143        """Directly execute `git {arg}`.
144
145        i.e. You can still do everything directly invoking git can do."""
146        git.execute(arg)

Directly execute git {arg}.

i.e. You can still do everything directly invoking git can do.

def do_new_repo(self, _: str):
148    def do_new_repo(self, _: str):
149        """Create a new git repo in this directory."""
150        git.new_repo()

Create a new git repo in this directory.

def do_new_branch(self, name: str):
152    def do_new_branch(self, name: str):
153        """Create and switch to a new branch named after the supplied arg."""
154        git.create_new_branch(name)

Create and switch to a new branch named after the supplied arg.

@with_parser(new_remote_parser)
def do_new_gh_remote(self, args: argshell.argshell.Namespace):
156    @with_parser(new_remote_parser)
157    def do_new_gh_remote(self, args: Namespace):
158        """Create a remote GitHub repository for this repo.
159
160        GitHub CLI must be installed and configured for this to work."""
161        name = Pathier.cwd().stem
162        git.create_remote(name, args.public)

Create a remote GitHub repository for this repo.

GitHub CLI must be installed and configured for this to work.

def do_initcommit(self, _: str):
164    def do_initcommit(self, _: str):
165        """Stage and commit all files with message "Initial Commit"."""
166        git.initcommit()

Stage and commit all files with message "Initial Commit".

def do_undo(self, _: str):
168    def do_undo(self, _: str):
169        """Undo all uncommitted changes."""
170        git.undo()

Undo all uncommitted changes.

@with_parser(amend_files_parser, [files_postparser])
def do_add(self, args: argshell.argshell.Namespace):
172    @with_parser(amend_files_parser, [files_postparser])
173    def do_add(self, args: Namespace):
174        """Stage a list of files.
175        If no files are given, all files will be added."""
176        git.add(None if not args.files else args.files)

Stage a list of files. If no files are given, all files will be added.

def do_commit(self, message: str):
178    def do_commit(self, message: str):
179        """Commit staged files with this message."""
180        if not message.startswith('"'):
181            message = '"' + message
182        if not message.endswith('"'):
183            message += '"'
184        git.commit(f"-m {message}")

Commit staged files with this message.

@with_parser(commit_files_parser, [files_postparser])
def do_commitf(self, args: argshell.argshell.Namespace):
186    @with_parser(commit_files_parser, [files_postparser])
187    def do_commitf(self, args: Namespace):
188        """Stage and commit a list of files."""
189        git.commit_files(args.files, args.message)

Stage and commit a list of files.

def do_commitall(self, message: str):
191    def do_commitall(self, message: str):
192        """Stage and commit all files with this message."""
193        if not message.startswith('"'):
194            message = '"' + message
195        if not message.endswith('"'):
196            message += '"'
197        git.add()
198        git.commit(f"-m {message}")

Stage and commit all files with this message.

def do_switch(self, branch_name: str):
200    def do_switch(self, branch_name: str):
201        """Switch to this branch."""
202        git.switch_branch(branch_name)

Switch to this branch.

def do_add_url(self, url: str):
204    def do_add_url(self, url: str):
205        """Add remote url for repo and push repo."""
206        git.add_remote_url(url)
207        git.push("-u origin main")

Add remote url for repo and push repo.

def do_push_new(self, branch_name: str):
209    def do_push_new(self, branch_name: str):
210        """Push this new branch to origin with -u flag."""
211        git.push_new_branch(branch_name)

Push this new branch to origin with -u flag.

def do_push(self, args: str):
213    def do_push(self, args: str):
214        """Execute `git push`.
215
216        `args` can be any additional args that `git push` accepts."""
217        git.push(args)

Execute git push.

args can be any additional args that git push accepts.

def do_pull(self, args: str):
219    def do_pull(self, args: str):
220        """Execute `git pull`.
221
222        `args` can be any additional args that `git pull` accepts."""
223        git.pull(args)

Execute git pull.

args can be any additional args that git pull accepts.

def do_list_branches(self, _: str):
225    def do_list_branches(self, _: str):
226        """Show local and remote branches."""
227        git.list_branches()

Show local and remote branches.

def do_loggy(self, _: str):
229    def do_loggy(self, _: str):
230        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
231        git.loggy()

Execute git --oneline --name-only --abbrev-commit --graph.

def do_merge(self, branch_name: str):
233    def do_merge(self, branch_name: str):
234        """Merge supplied `branch_name` with the currently active branch."""
235        git.merge(branch_name)

Merge supplied branch_name with the currently active branch.

def do_tag(self, tag_id: str):
237    def do_tag(self, tag_id: str):
238        """Tag current commit with `tag_id`."""
239        git.tag(tag_id)

Tag current commit with tag_id.

@with_parser(amend_files_parser, [files_postparser])
def do_amend(self, args: argshell.argshell.Namespace):
241    @with_parser(amend_files_parser, [files_postparser])
242    def do_amend(self, args: Namespace):
243        """Stage files and add to previous commit."""
244        git.amend(args.files)

Stage files and add to previous commit.

@with_parser(delete_branch_parser)
def do_delete_branch(self, args: argshell.argshell.Namespace):
246    @with_parser(delete_branch_parser)
247    def do_delete_branch(self, args: Namespace):
248        """Delete branch."""
249        git.delete_branch(args.branch, not args.remote)

Delete branch.

def do_pull_branch(self, branch: str):
251    def do_pull_branch(self, branch: str):
252        """Pull this branch from the origin."""
253        git.pull_branch(branch)

Pull this branch from the origin.

def do_ignore(self, patterns: str):
255    def do_ignore(self, patterns: str):
256        """Add the list of patterns to `.gitignore`."""
257        patterns = "\n".join(patterns.split())
258        path = Pathier(".gitignore")
259        path.append("\n")
260        path.append(patterns, False)

Add the list of patterns to .gitignore.

def do_make_private(self, owner: str):
262    def do_make_private(self, owner: str):
263        """Make the GitHub remote for this repo private.
264
265        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
266
267        This repo must exist and GitHub CLI must be installed and configured."""
268        git.make_private(owner, Pathier.cwd().stem)

Make the GitHub remote for this repo private.

Expects an argument for the repo owner, i.e. the OWNER in github.com/{OWNER}/{repo-name}

This repo must exist and GitHub CLI must be installed and configured.

def do_make_public(self, owner: str):
270    def do_make_public(self, owner: str):
271        """Make the GitHub remote for this repo public.
272
273        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
274
275        This repo must exist and GitHub CLI must be installed and configured."""
276        git.make_public(owner, Pathier.cwd().stem)

Make the GitHub remote for this repo public.

Expects an argument for the repo owner, i.e. the OWNER in github.com/{OWNER}/{repo-name}

This repo must exist and GitHub CLI must be installed and configured.

def do_delete_gh_repo(self, owner: str):
278    def do_delete_gh_repo(self, owner: str):
279        """Delete this repo from GitHub.
280
281        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
282
283        GitHub CLI must be installed and configured.
284
285        May require you to reauthorize and rerun command."""
286        git.delete_remote(owner, Pathier.cwd().stem)

Delete this repo from GitHub.

Expects an argument for the repo owner, i.e. the OWNER in github.com/{OWNER}/{repo-name}

GitHub CLI must be installed and configured.

May require you to reauthorize and rerun command.

Inherited Members
cmd.Cmd
Cmd
precmd
postcmd
preloop
postloop
parseline
onecmd
emptyline
completedefault
completenames
complete
get_names
complete_help
print_topics
columnize
argshell.argshell.ArgShell
do_quit
do_sys
cmdloop
def main():
289def main():
290    GitBetter().cmdloop()