gitws.git module

Our Git Helper.

We know, that there are libraries for that. But we just want to have a lean programmatic interface to git. Just with the functionality we need. Not more.

We currently do NOT check the git version and try to use the common subset.

class gitws.git.BranchStatus(*, info: str)[source]

Bases: Status

Branch Status Line From git status command.

>>> branchstatus = BranchStatus.from_str('main...origin/main')
>>> branchstatus
BranchStatus(info='main...origin/main')
>>> str(branchstatus)
'main...origin/main'
static from_str(line) BranchStatus[source]

Create from git status --porcelain Output.

info: str

Branch Status String.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'info': FieldInfo(annotation=str, required=True)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

with_path(path: Path) BranchStatus[source]

Return BranchStatus with path as prefix.

class gitws.git.DiffStat(*, path: Path, stat: str)[source]

Bases: BaseModel

Diff Status Line From git diff --stat command.

>>> diffstat = DiffStat.from_str(' path/file.txt | 16 ++++++++--------')
>>> diffstat
DiffStat(path=PosixPath('path/file.txt'), stat='16 ++++++++--------')
>>> str(diffstat)
' path/file.txt | 16 ++++++++--------'
>>> str(diffstat.with_path(Path('base')))
' base/path/file.txt | 16 ++++++++--------'
static from_str(line) DiffStat[source]

Create from git diff --stat Output.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'path': FieldInfo(annotation=Path, required=True), 'stat': FieldInfo(annotation=str, required=True)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

path: Path

File Path.

stat: str

Diff Status Line.

with_path(path: Path) DiffStat[source]

Return DiffStat with path as prefix.

class gitws.git.FileStatus(*, index: State, work: State, path: Path, orig_path: Optional[Path] = None)[source]

Bases: Status

Git File Status Line.

>>> status = FileStatus.from_str("?? file.txt")
>>> status
FileStatus(index=<State.UNTRACKED: '?'>, work=<State.UNTRACKED: '?'>, path=PosixPath('file.txt'))
>>> str(status)
'?? file.txt'
>>> str(status.with_path(Path("base")))
'?? base/file.txt'
>>> status = FileStatus.from_str("R  src -> dest")
>>> status
FileStatus(index=<State.RENAMED: 'R'>, work=<State.UNMODIFIED: ' '>, path=PosixPath('dest'), orig_path=...
>>> str(status)
'R  src -> dest'
>>> str(status.with_path(Path("base")))
'R  base/src -> base/dest'
static from_str(line) FileStatus[source]

Create from git status --porcelain Output.

has_index_changes() bool[source]

Has Index Changes.

has_work_changes() bool[source]

Has Work Changes.

index: State

Status of the Index.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'index': FieldInfo(annotation=State, required=True), 'orig_path': FieldInfo(annotation=Union[Path, NoneType], required=False), 'path': FieldInfo(annotation=Path, required=True), 'work': FieldInfo(annotation=State, required=True)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

orig_path: Optional[Path]

File Path of the original file in case of a move.

path: Path

File Path.

with_path(path: Path) FileStatus[source]

Return FileStatus with path as prefix.

work: State

Status of Working Tree.

class gitws.git.Git(path: Path, clone_cache: Optional[Path] = None, secho=None)[source]

Bases: object

Work with git repositories.

To initialize a git repository in the current working directory:

>>> Git.init()
Git(...)

The easiest way to start with an existing clone:

>>> git = Git.from_path()
add(paths: Optional[Tuple[Path, ...]] = None, force: bool = False, all_: bool = False)[source]

Add Files.

Parameters:

paths – File Paths to add.

Keyword Arguments:
  • force – allow adding otherwise ignored files.

  • all – add changes from all tracked and untracked files.

check()[source]

Check Clone for Existence.

checkout(revision: Optional[str] = None, paths: Optional[Tuple[Path, ...]] = None, branch: Optional[str] = None, force: bool = False)[source]

Checkout Revision.

Keyword Arguments:
  • revision – Revision to checkout.

  • paths – File Paths to checkout, otherwise entire repo.

  • branch – Branch to be checked out.

  • force – Overwrite local changes.

clone(url, revision: Optional[str] = None, depth: Optional[int] = None)[source]

Clone url and checkout revision.

The checkout is done to self.path. If self.clone_cache directory path is set, the clone uses the given path as local filesystem cache.

commit(msg: str, paths: Optional[Tuple[Path, ...]] = None, all_: bool = False)[source]

Commit.

Parameters:

msg – Commit Message

Keyword Arguments:
  • paths – Paths.

  • all – commit all changed files

diff(paths: Optional[Tuple[Path, ...]] = None, prefix: Optional[Path] = None)[source]

Display Git Diff.

Keyword Arguments:
  • paths – Paths.

  • prefix – Path Prefix.

diffstat(paths: Optional[Tuple[Path, ...]] = None) Iterator[DiffStat][source]

Git Diff Statistics.

Keyword Arguments:

paths – Paths.

fetch(shallow: Optional[str] = None, unshallow: bool = False)[source]

Fetch.

static find_path(path: Optional[Path] = None) Path[source]

Determine Top Directory of Git Clone.

static from_path(path: Optional[Path] = None, secho=None) Git[source]

Create GIT Repo Helper from path.

get_branch() Optional[str][source]

Get Current Branch.

get_revision() Optional[str][source]

Get Revision.

We try several things, the winner takes it all:

  1. Get Current Tag

  2. Get Current Branch

  3. Get SHA.

  4. None if empty repo.

get_sha(revision: Optional[str] = None) Optional[str][source]

Get Current SHA.

get_shallow() Optional[str][source]

Get Shallow.

get_tag() Optional[str][source]

Get Current Tag.

get_tags(pattern: Optional[str] = None) Tuple[str, ...][source]

Get Tags matching pattern or all.

get_upstream_branch() Optional[str][source]

Get Current Upstream Branch.

get_url() Optional[str][source]

Get Current URL of origin.

has_changes() bool[source]

Let you know if work has changes.

has_index_changes() bool[source]

Let you know if index has changes.

has_work_changes() bool[source]

Let you know if work has changes.

static init(path: Optional[Path] = None) Git[source]

Initialize new git repository at path.

is_cloned() bool[source]

Determine if clone already exists.

is_empty()[source]

Clone does not contain any changes.

A clone is empty if there are:

  • no files changed

  • no commits which are not pushed yet

  • nothing stashed

merge(commit)[source]

Merge.

rebase()[source]

Rebase.

reset(paths: Tuple[Path, ...])[source]

Reset Files.

Parameters:

paths – File paths.

rm(paths: Tuple[Path, ...], cached: bool = False, force: bool = False, recursive: bool = False)[source]

Remove Files.

Parameters:

paths – files and/or directories to be removed

Keyword Arguments:
  • cached – only remove from the index

  • force – override the up-to-date check

  • recursive – allow recursive removal

set_config(name, value)[source]

Set Git Configuration Variable name to value.

status(paths: Optional[Tuple[Path, ...]] = None, branch: bool = False) Iterator[Status][source]

Git Status.

Keyword Arguments:
  • paths – files and/or directories to be checked

  • branch – Show branch too.

submodule_update(init: bool = False, recursive: bool = False)[source]

Submodule Update.

Keyword Arguments:
  • init – Initialize.

  • recursive – Recursive.

tag(name: str, msg: Optional[str] = None, force: bool = False)[source]

Create Tag.

Parameters:

name – Tag Name.

Keyword Arguments:
  • msg – Message.

  • force – Replace tag if exists.

class gitws.git.State(value)[source]

Bases: Enum

Current State (Part of git status line).

>>> State(" ")
<State.UNMODIFIED: ' '>
>>> State("A")
<State.ADDED: 'A'>
ADDED = 'A'
COPIED = 'C'
DELETED = 'D'
IGNORED = '!'
MODIFIED = 'M'
RENAMED = 'R'
TYPE_CHANGED = 'T'
UNMODIFIED = ' '
UNTRACKED = '?'
UPDATED_UNMERGED = 'U'
class gitws.git.Status[source]

Bases: BaseModel

Status (One git status line).

has_changes() Optional[bool][source]

Has Changes.

has_index_changes() Optional[bool][source]

Has Index Changes.

has_work_changes() Optional[bool][source]

Has Work Changes.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

with_path(path: Path) Status[source]

Return Status with path as prefix.