Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Clements authored and Conan-Kudo committed Mar 21, 2022
0 parents commit 0b5bb2c
Show file tree
Hide file tree
Showing 21 changed files with 2,808 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.env
.idea/
__pycache__/
config.json
373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

167 changes: 167 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
git river
=========

`git river workspace` will manage a "workspace" path you configure, cloning
and managing repositories from configured GitHub and GitLab groups.

Repositories will be organized by the domain and path of the remote GitHub
repository or GitLab project.

```
$ tree ~/workspace
~/workspace
├── github.com
│ └── datto
│ └── example
└── gitlab.com
└── datto
└── example
```

Links
-----

* [Source code](https://github.com/datto/git-river/)
* [Packages](https://pypi.org/project/git-river/)

Installation
------------

`git-river` requires Python 3.9 or above.

```
pip3 install git-river
```

Usage
-----

Run `git-river <subcommand>`. Git's builtin aliasing also allows you to
run `git river` instead.

```bash
git-river --help
```

- `git river config` displays the current configuration.

- `git river workspace` manages the workspace path.

Run without any subcommand, it runs all workspace subcommands except `list`
and `fetch`.

- `git river workspace clone` clones repositories.
- `git river workspace configure` sets git config options.
- `git river workspace fetch` fetches each git remote.
- `git river workspace list` displays remote repos that will be cloned.
- `git river workspace remotes` sets `upstream` and `origin` remotes.
- `git river workspace tidy` deletes merged branches.

- `git river repo` manages the repository in the current directory.

This mostly matches the features from the `workspace` subcommand.

- `git river repo configure` sets git config options.
- `git river repo fetch` fetches each git remote.
- `git river repo remotes` sets `upstream` and `origin` remotes.
- `git river repo tidy` deletes merged branches.

Configuration
-------------

Configuration is a JSON object read from `~/.config/git-river/config.json`.

- `path` - path to a directory to use as the "workspace".
- `forges` - a map of forges.

Forges have the following options. Only `type` is required - the default
configuration is to use the main public GitHub or GitLab domain without
authentication.

- `type` (required) - The type of the instance, either `github` or `gitlab`.
- `base_url` (optional) - Base url of the instance. Should not include a trailing slash.
- Default for GitHub instances is `https://api.github.com`.
- Default for GitLab instances is `https://gitlab.com`.
- `login_or_token` (optional, GitHub only) - Authentication token.
- `private_token` (optional, GitLab only) - Authentication token.
- `gitconfig` (default: `{}`) - A key-value map of git config options to set on repositories.
- `groups` (default: `[]`) - Include repositories from specific groups.
- `users` (default: `[]`) - Include repositories from specific users.
- `self` (default: `true`) - Automatically include the authenticated user's repositories.


### Example

```json
{
"workspace": "~/Development",
"forges": {
"gitlab": {
"type": "gitlab",
"base_url": "https://gitlab.com",
"private_token": "...",
"groups": [],
"users": [],
"self": true,
"gitconfig": {
"user.email": "[email protected]"
}
},
"github": {
"type": "github",
"login_or_token": "...",
"groups": [],
"users": [],
"gitconfig": {
"user.email": "[email protected]"
}
}
}
}
```

Development
-----------

[Poetry][poetry] is used to develop, build, and package git-river. Poetry's
[documentation][poetry/docs] describes how to install it on your OS. Once you've
installed it, create a virtual environment containing git-river and it's
dependencies with `poetry install`.

You can then run the local version of the CLI with `poetry run git-river`.

Code is formatted using [black], run with `poetry run black git_river`.

Types are checked using [mypy], run with `poetry run mypy git_river`.

Tests are written using [pytest], run with `poetry run pytest`.

```bash
# Download the project and install dependencies
git clone https://github.com/datto/git-river.git
cd git-river
poetry install

# Use the local version of the CLI
poetry run git-river ...

# Test, lint and format code
poetry run black git_river
poetry run mypy git_river
poetry run pytest
```

License
-------

Licensed under the Mozilla Public License Version 2.0.

Copyright Datto, Inc.

Authored by [Sam Clements](https://github.com/borntyping).

[black]: https://github.com/psf/black
[mypy]: https://mypy.readthedocs.io/en/stable/
[poetry/docs]: https://python-poetry.org/docs/
[poetry]: https://python-poetry.org/
[pytest]: https://docs.pytest.org/
19 changes: 19 additions & 0 deletions git_river/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This file is part of git-river.
#
# Copyright Datto, Inc.
# Author: Sam Clements <[email protected]>
#
# Licensed under the Mozilla Public License Version 2.0.
# Fedora-License-Identifier: MPLv2.0
# SPDX-2.0-License-Identifier: MPL-2.0
# SPDX-3.0-License-Identifier: MPL-2.0
#
# git-river is open source software.
# For more information on the license, see LICENSE.
# For more information on open source software, see https://opensource.org/osd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

__app__ = "git-river"
21 changes: 21 additions & 0 deletions git_river/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This file is part of git-river.
#
# Copyright Datto, Inc.
# Author: Sam Clements <[email protected]>
#
# Licensed under the Mozilla Public License Version 2.0.
# Fedora-License-Identifier: MPLv2.0
# SPDX-2.0-License-Identifier: MPL-2.0
# SPDX-3.0-License-Identifier: MPL-2.0
#
# git-river is open source software.
# For more information on the license, see LICENSE.
# For more information on open source software, see https://opensource.org/osd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import git_river.cli

git_river.cli.main()
52 changes: 52 additions & 0 deletions git_river/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This file is part of git-river.
#
# Copyright Datto, Inc.
# Author: Sam Clements <[email protected]>
#
# Licensed under the Mozilla Public License Version 2.0.
# Fedora-License-Identifier: MPLv2.0
# SPDX-2.0-License-Identifier: MPL-2.0
# SPDX-3.0-License-Identifier: MPL-2.0
#
# git-river is open source software.
# For more information on the license, see LICENSE.
# For more information on open source software, see https://opensource.org/osd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import click
import pydantic.error_wrappers

import git_river
import git_river.commands
import git_river.commands.clone
import git_river.commands.forge
import git_river.commands.config
import git_river.commands.repo
import git_river.config


@click.group()
@click.pass_context
def main(ctx: click.Context) -> None:
git_river.config.configure_logging()
try:
ctx.obj = git_river.config.Config()
except pydantic.error_wrappers.ValidationError as error:
raise click.UsageError(str(error)) from error


main.add_command(git_river.commands.clone.main)
main.add_command(git_river.commands.config.display_config)
main.add_command(git_river.commands.config.display_workspace)
main.add_command(git_river.commands.config.init_config)
main.add_command(git_river.commands.forge.main)
main.add_command(git_river.commands.repo.configure_options)
main.add_command(git_river.commands.repo.configure_remotes)
main.add_command(git_river.commands.repo.fetch_remotes)
main.add_command(git_river.commands.repo.merge_feature_branches)
main.add_command(git_river.commands.repo.tidy_branches)
main.add_command(git_river.commands.repo.restart)
main.add_command(git_river.commands.repo.end)
Empty file added git_river/commands/__init__.py
Empty file.
41 changes: 41 additions & 0 deletions git_river/commands/clone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This file is part of git-river.
#
# Copyright Datto, Inc.
# Author: Sam Clements <[email protected]>
#
# Licensed under the Mozilla Public License Version 2.0.
# Fedora-License-Identifier: MPLv2.0
# SPDX-2.0-License-Identifier: MPL-2.0
# SPDX-3.0-License-Identifier: MPL-2.0
#
# git-river is open source software.
# For more information on the license, see LICENSE.
# For more information on open source software, see https://opensource.org/osd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import typing

import click
import structlog

import git_river.config
import git_river.ext.click

logger = structlog.get_logger(logger_name=__name__)


@click.command(name="clone")
@click.argument(
"repositories",
metavar="REPOSITORY",
type=click.STRING,
nargs=-1,
)
@click.pass_obj
def main(config: git_river.config.Config, repositories: typing.Sequence[str]) -> None:
"""Clone a repository to the workspace path."""
for url in repositories:
config.repository_from_url(url).clone(verbose=True)
64 changes: 64 additions & 0 deletions git_river/commands/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# This file is part of git-river.
#
# Copyright Datto, Inc.
# Author: Sam Clements <[email protected]>
#
# Licensed under the Mozilla Public License Version 2.0.
# Fedora-License-Identifier: MPLv2.0
# SPDX-2.0-License-Identifier: MPL-2.0
# SPDX-3.0-License-Identifier: MPL-2.0
#
# git-river is open source software.
# For more information on the license, see LICENSE.
# For more information on open source software, see https://opensource.org/osd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
import pathlib

import click

import git_river
import git_river.commands
import git_river.commands.clone
import git_river.commands.forge
import git_river.commands.repo
import git_river.config


@click.command(name="config")
@click.pass_obj
def display_config(config: git_river.config.Config) -> None:
"""Dump the current configuration as JSON."""
print(config.json(indent=2, by_alias=True))


@click.command(name="init")
@click.argument(
"workspace",
type=click.Path(
exists=False,
file_okay=False,
dir_okay=True,
path_type=pathlib.Path,
),
)
@click.pass_obj
def init_config(config: git_river.config.Config, workspace: str) -> None:
config.workspace = pathlib.Path(workspace)

if git_river.config.CONFIG_PATH.exists():
raise click.UsageError(f"Config file {git_river.config.CONFIG_PATH} already exists")

if not git_river.config.CONFIG_DIRECTORY.exists():
git_river.config.CONFIG_DIRECTORY.mkdir()

git_river.config.CONFIG_PATH.write_text(config.json(indent=2, by_alias=True))


@click.command(name="workspace")
@click.pass_obj
def display_workspace(config: git_river.config.Config) -> None:
"""Print the workspace path."""
print(config.workspace)
Loading

0 comments on commit 0b5bb2c

Please sign in to comment.