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 `cmd` 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_cmd(self, command: str):
142        """Execute arbitrary command in the terminal so you don't have to quit gitbetter to run other programs/commands."""
143        os.system(command)
144
145    def do_git(self, arg: str):
146        """Directly execute `git {arg}`.
147
148        i.e. You can still do everything directly invoking git can do."""
149        git.execute(arg)
150
151    def do_new_repo(self, _: str):
152        """Create a new git repo in this directory."""
153        git.new_repo()
154
155    def do_new_branch(self, name: str):
156        """Create and switch to a new branch named after the supplied arg."""
157        git.create_new_branch(name)
158
159    @with_parser(new_remote_parser)
160    def do_new_gh_remote(self, args: Namespace):
161        """Create a remote GitHub repository for this repo.
162
163        GitHub CLI must be installed and configured for this to work."""
164        name = Pathier.cwd().stem
165        git.create_remote(name, args.public)
166
167    def do_initcommit(self, _: str):
168        """Stage and commit all files with message "Initial Commit"."""
169        git.initcommit()
170
171    def do_undo(self, _: str):
172        """Undo all uncommitted changes."""
173        git.undo()
174
175    @with_parser(amend_files_parser, [files_postparser])
176    def do_add(self, args: Namespace):
177        """Stage a list of files.
178        If no files are given, all files will be added."""
179        git.add(None if not args.files else args.files)
180
181    def do_commit(self, message: str):
182        """Commit staged files with this message."""
183        if not message.startswith('"'):
184            message = '"' + message
185        if not message.endswith('"'):
186            message += '"'
187        git.commit(f"-m {message}")
188
189    @with_parser(commit_files_parser, [files_postparser])
190    def do_commitf(self, args: Namespace):
191        """Stage and commit a list of files."""
192        git.commit_files(args.files, args.message)
193
194    def do_commitall(self, message: str):
195        """Stage and commit all files with this message."""
196        if not message.startswith('"'):
197            message = '"' + message
198        if not message.endswith('"'):
199            message += '"'
200        git.add()
201        git.commit(f"-m {message}")
202
203    def do_switch(self, branch_name: str):
204        """Switch to this branch."""
205        git.switch_branch(branch_name)
206
207    def do_add_url(self, url: str):
208        """Add remote url for repo and push repo."""
209        git.add_remote_url(url)
210        git.push("-u origin main")
211
212    def do_push_new(self, branch_name: str):
213        """Push this new branch to origin with -u flag."""
214        git.push_new_branch(branch_name)
215
216    def do_push(self, args: str):
217        """Execute `git push`.
218
219        `args` can be any additional args that `git push` accepts."""
220        git.push(args)
221
222    def do_pull(self, args: str):
223        """Execute `git pull`.
224
225        `args` can be any additional args that `git pull` accepts."""
226        git.pull(args)
227
228    def do_list_branches(self, _: str):
229        """Show local and remote branches."""
230        git.list_branches()
231
232    def do_loggy(self, _: str):
233        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
234        git.loggy()
235
236    def do_merge(self, branch_name: str):
237        """Merge supplied `branch_name` with the currently active branch."""
238        git.merge(branch_name)
239
240    def do_tag(self, tag_id: str):
241        """Tag current commit with `tag_id`."""
242        git.tag(tag_id)
243
244    @with_parser(amend_files_parser, [files_postparser])
245    def do_amend(self, args: Namespace):
246        """Stage files and add to previous commit."""
247        git.amend(args.files)
248
249    @with_parser(delete_branch_parser)
250    def do_delete_branch(self, args: Namespace):
251        """Delete branch."""
252        git.delete_branch(args.branch, not args.remote)
253
254    def do_pull_branch(self, branch: str):
255        """Pull this branch from the origin."""
256        git.pull_branch(branch)
257
258    def do_ignore(self, patterns: str):
259        """Add the list of patterns to `.gitignore`."""
260        patterns = "\n".join(patterns.split())
261        path = Pathier(".gitignore")
262        path.append("\n")
263        path.append(patterns, False)
264
265    def do_make_private(self, owner: str):
266        """Make the GitHub remote for this repo private.
267
268        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
269
270        This repo must exist and GitHub CLI must be installed and configured."""
271        git.make_private(owner, Pathier.cwd().stem)
272
273    def do_make_public(self, owner: str):
274        """Make the GitHub remote for this repo public.
275
276        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
277
278        This repo must exist and GitHub CLI must be installed and configured."""
279        git.make_public(owner, Pathier.cwd().stem)
280
281    def do_delete_gh_repo(self, owner: str):
282        """Delete this repo from GitHub.
283
284        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
285
286        GitHub CLI must be installed and configured.
287
288        May require you to reauthorize and rerun command."""
289        git.delete_remote(owner, Pathier.cwd().stem)
290
291
292def main():
293    GitBetter().cmdloop()
294
295
296if __name__ == "__main__":
297    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 `cmd` 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_cmd(self, command: str):
143        """Execute arbitrary command in the terminal so you don't have to quit gitbetter to run other programs/commands."""
144        os.system(command)
145
146    def do_git(self, arg: str):
147        """Directly execute `git {arg}`.
148
149        i.e. You can still do everything directly invoking git can do."""
150        git.execute(arg)
151
152    def do_new_repo(self, _: str):
153        """Create a new git repo in this directory."""
154        git.new_repo()
155
156    def do_new_branch(self, name: str):
157        """Create and switch to a new branch named after the supplied arg."""
158        git.create_new_branch(name)
159
160    @with_parser(new_remote_parser)
161    def do_new_gh_remote(self, args: Namespace):
162        """Create a remote GitHub repository for this repo.
163
164        GitHub CLI must be installed and configured for this to work."""
165        name = Pathier.cwd().stem
166        git.create_remote(name, args.public)
167
168    def do_initcommit(self, _: str):
169        """Stage and commit all files with message "Initial Commit"."""
170        git.initcommit()
171
172    def do_undo(self, _: str):
173        """Undo all uncommitted changes."""
174        git.undo()
175
176    @with_parser(amend_files_parser, [files_postparser])
177    def do_add(self, args: Namespace):
178        """Stage a list of files.
179        If no files are given, all files will be added."""
180        git.add(None if not args.files else args.files)
181
182    def do_commit(self, message: str):
183        """Commit staged files with this message."""
184        if not message.startswith('"'):
185            message = '"' + message
186        if not message.endswith('"'):
187            message += '"'
188        git.commit(f"-m {message}")
189
190    @with_parser(commit_files_parser, [files_postparser])
191    def do_commitf(self, args: Namespace):
192        """Stage and commit a list of files."""
193        git.commit_files(args.files, args.message)
194
195    def do_commitall(self, message: str):
196        """Stage and commit all files with this message."""
197        if not message.startswith('"'):
198            message = '"' + message
199        if not message.endswith('"'):
200            message += '"'
201        git.add()
202        git.commit(f"-m {message}")
203
204    def do_switch(self, branch_name: str):
205        """Switch to this branch."""
206        git.switch_branch(branch_name)
207
208    def do_add_url(self, url: str):
209        """Add remote url for repo and push repo."""
210        git.add_remote_url(url)
211        git.push("-u origin main")
212
213    def do_push_new(self, branch_name: str):
214        """Push this new branch to origin with -u flag."""
215        git.push_new_branch(branch_name)
216
217    def do_push(self, args: str):
218        """Execute `git push`.
219
220        `args` can be any additional args that `git push` accepts."""
221        git.push(args)
222
223    def do_pull(self, args: str):
224        """Execute `git pull`.
225
226        `args` can be any additional args that `git pull` accepts."""
227        git.pull(args)
228
229    def do_list_branches(self, _: str):
230        """Show local and remote branches."""
231        git.list_branches()
232
233    def do_loggy(self, _: str):
234        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
235        git.loggy()
236
237    def do_merge(self, branch_name: str):
238        """Merge supplied `branch_name` with the currently active branch."""
239        git.merge(branch_name)
240
241    def do_tag(self, tag_id: str):
242        """Tag current commit with `tag_id`."""
243        git.tag(tag_id)
244
245    @with_parser(amend_files_parser, [files_postparser])
246    def do_amend(self, args: Namespace):
247        """Stage files and add to previous commit."""
248        git.amend(args.files)
249
250    @with_parser(delete_branch_parser)
251    def do_delete_branch(self, args: Namespace):
252        """Delete branch."""
253        git.delete_branch(args.branch, not args.remote)
254
255    def do_pull_branch(self, branch: str):
256        """Pull this branch from the origin."""
257        git.pull_branch(branch)
258
259    def do_ignore(self, patterns: str):
260        """Add the list of patterns to `.gitignore`."""
261        patterns = "\n".join(patterns.split())
262        path = Pathier(".gitignore")
263        path.append("\n")
264        path.append(patterns, False)
265
266    def do_make_private(self, owner: str):
267        """Make the GitHub remote for this repo private.
268
269        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
270
271        This repo must exist and GitHub CLI must be installed and configured."""
272        git.make_private(owner, Pathier.cwd().stem)
273
274    def do_make_public(self, owner: str):
275        """Make the GitHub remote for this repo public.
276
277        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
278
279        This repo must exist and GitHub CLI must be installed and configured."""
280        git.make_public(owner, Pathier.cwd().stem)
281
282    def do_delete_gh_repo(self, owner: str):
283        """Delete this repo from GitHub.
284
285        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
286
287        GitHub CLI must be installed and configured.
288
289        May require you to reauthorize and rerun command."""
290        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 `cmd` 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 cmd 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_cmd(self, command: str):
142    def do_cmd(self, command: str):
143        """Execute arbitrary command in the terminal so you don't have to quit gitbetter to run other programs/commands."""
144        os.system(command)

Execute arbitrary command in the terminal so you don't have to quit gitbetter to run other programs/commands.

def do_git(self, arg: str):
146    def do_git(self, arg: str):
147        """Directly execute `git {arg}`.
148
149        i.e. You can still do everything directly invoking git can do."""
150        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):
152    def do_new_repo(self, _: str):
153        """Create a new git repo in this directory."""
154        git.new_repo()

Create a new git repo in this directory.

def do_new_branch(self, name: str):
156    def do_new_branch(self, name: str):
157        """Create and switch to a new branch named after the supplied arg."""
158        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):
160    @with_parser(new_remote_parser)
161    def do_new_gh_remote(self, args: Namespace):
162        """Create a remote GitHub repository for this repo.
163
164        GitHub CLI must be installed and configured for this to work."""
165        name = Pathier.cwd().stem
166        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):
168    def do_initcommit(self, _: str):
169        """Stage and commit all files with message "Initial Commit"."""
170        git.initcommit()

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

def do_undo(self, _: str):
172    def do_undo(self, _: str):
173        """Undo all uncommitted changes."""
174        git.undo()

Undo all uncommitted changes.

@with_parser(amend_files_parser, [files_postparser])
def do_add(self, args: argshell.argshell.Namespace):
176    @with_parser(amend_files_parser, [files_postparser])
177    def do_add(self, args: Namespace):
178        """Stage a list of files.
179        If no files are given, all files will be added."""
180        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):
182    def do_commit(self, message: str):
183        """Commit staged files with this message."""
184        if not message.startswith('"'):
185            message = '"' + message
186        if not message.endswith('"'):
187            message += '"'
188        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):
190    @with_parser(commit_files_parser, [files_postparser])
191    def do_commitf(self, args: Namespace):
192        """Stage and commit a list of files."""
193        git.commit_files(args.files, args.message)

Stage and commit a list of files.

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

Stage and commit all files with this message.

def do_switch(self, branch_name: str):
204    def do_switch(self, branch_name: str):
205        """Switch to this branch."""
206        git.switch_branch(branch_name)

Switch to this branch.

def do_add_url(self, url: str):
208    def do_add_url(self, url: str):
209        """Add remote url for repo and push repo."""
210        git.add_remote_url(url)
211        git.push("-u origin main")

Add remote url for repo and push repo.

def do_push_new(self, branch_name: str):
213    def do_push_new(self, branch_name: str):
214        """Push this new branch to origin with -u flag."""
215        git.push_new_branch(branch_name)

Push this new branch to origin with -u flag.

def do_push(self, args: str):
217    def do_push(self, args: str):
218        """Execute `git push`.
219
220        `args` can be any additional args that `git push` accepts."""
221        git.push(args)

Execute git push.

args can be any additional args that git push accepts.

def do_pull(self, args: str):
223    def do_pull(self, args: str):
224        """Execute `git pull`.
225
226        `args` can be any additional args that `git pull` accepts."""
227        git.pull(args)

Execute git pull.

args can be any additional args that git pull accepts.

def do_list_branches(self, _: str):
229    def do_list_branches(self, _: str):
230        """Show local and remote branches."""
231        git.list_branches()

Show local and remote branches.

def do_loggy(self, _: str):
233    def do_loggy(self, _: str):
234        """Execute `git --oneline --name-only --abbrev-commit --graph`."""
235        git.loggy()

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

def do_merge(self, branch_name: str):
237    def do_merge(self, branch_name: str):
238        """Merge supplied `branch_name` with the currently active branch."""
239        git.merge(branch_name)

Merge supplied branch_name with the currently active branch.

def do_tag(self, tag_id: str):
241    def do_tag(self, tag_id: str):
242        """Tag current commit with `tag_id`."""
243        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):
245    @with_parser(amend_files_parser, [files_postparser])
246    def do_amend(self, args: Namespace):
247        """Stage files and add to previous commit."""
248        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):
250    @with_parser(delete_branch_parser)
251    def do_delete_branch(self, args: Namespace):
252        """Delete branch."""
253        git.delete_branch(args.branch, not args.remote)

Delete branch.

def do_pull_branch(self, branch: str):
255    def do_pull_branch(self, branch: str):
256        """Pull this branch from the origin."""
257        git.pull_branch(branch)

Pull this branch from the origin.

def do_ignore(self, patterns: str):
259    def do_ignore(self, patterns: str):
260        """Add the list of patterns to `.gitignore`."""
261        patterns = "\n".join(patterns.split())
262        path = Pathier(".gitignore")
263        path.append("\n")
264        path.append(patterns, False)

Add the list of patterns to .gitignore.

def do_make_private(self, owner: str):
266    def do_make_private(self, owner: str):
267        """Make the GitHub remote for this repo private.
268
269        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
270
271        This repo must exist and GitHub CLI must be installed and configured."""
272        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):
274    def do_make_public(self, owner: str):
275        """Make the GitHub remote for this repo public.
276
277        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
278
279        This repo must exist and GitHub CLI must be installed and configured."""
280        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):
282    def do_delete_gh_repo(self, owner: str):
283        """Delete this repo from GitHub.
284
285        Expects an argument for the repo owner, i.e. the `OWNER` in `github.com/{OWNER}/{repo-name}`
286
287        GitHub CLI must be installed and configured.
288
289        May require you to reauthorize and rerun command."""
290        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
cmdloop
def main():
293def main():
294    GitBetter().cmdloop()