Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions git_tool/__main__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import typer
from git_tool.ci.subcommands.feature_add import app as feature_add
from git_tool.ci.subcommands.feature_blame import app as feature_blame
from git_tool.ci.subcommands.feature_commit import app as feature_commit
from git_tool.ci.subcommands.feature_info import app as feature_info
from git_tool.ci.subcommands.feature_status import app as feature_status

app = typer.Typer(name="features")
app.add_typer(feature_add, name="add")
app.add_typer(feature_blame, name="blame")
app.add_typer(feature_commit, name="commit")
app.add_typer(feature_info, name="info")
app.add_typer(feature_status, name="status")

from git_tool.ci.subcommands.feature_add import feature_add_by_add
from git_tool.ci.subcommands.feature_add_from_staged import features_from_staging_area
from git_tool.ci.subcommands.feature_blame import feature_blame
from git_tool.ci.subcommands.feature_commit import feature_commit
from git_tool.ci.subcommands.feature_commit_msg import feature_commit_msg
from git_tool.ci.subcommands.feature_commits import app as feature_commits
from git_tool.ci.subcommands.feature_info import inspect_feature
from git_tool.ci.subcommands.feature_info_all import all_feature_info
from git_tool.ci.subcommands.feature_pre_commit import feature_pre_commit
from git_tool.ci.subcommands.feature_status import feature_status


app = typer.Typer(name="feature") # "git feature --help" does not work, but "git-feature --help" does
app.command(name="add", help="Stage files and associate them with the provided features.")(feature_add_by_add)
app.command(name="add-from-staged", help="Associate staged files with features.")(features_from_staging_area)
app.command(name="blame", help="Display features associated with file lines.")(feature_blame)
app.command(name="commit", help="Associate an existing commit with one or more features.")(feature_commit)
app.command(name="commit-msg", help="Generate feature information for the commit message.")(feature_commit_msg)
app.add_typer(feature_commits, name="commits", help="Find all commits that have feature information associated.")
app.command(name="info", help="Show information of a specific feature.")(inspect_feature)
app.command(name="info-all", help="List all available features in the project.")(all_feature_info)
app.command(name="pre-commit", help="Check if all staged changes are properly associated with features.")(feature_pre_commit)
app.command(name="status", help="Display unstaged and staged changes with associated features.")(feature_status)


app()
44 changes: 1 addition & 43 deletions git_tool/ci/subcommands/feature_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
app = typer.Typer(no_args_is_help=True)


@app.command("by-add", no_args_is_help=True)
@app.command("add", help="Stage files and associate them with the provided features.", no_args_is_help=True)
def feature_add_by_add(
feature_names: list[str] = typer.Argument(
None, help="List of feature names to associate with the staged files"
Expand Down Expand Up @@ -52,48 +52,6 @@ def feature_add_by_add(
typer.echo("No features provided.", err=True)


@app.command("from-staged", help="Associate staged files with features")
def features_from_staging_area():
"""
Use the staged files to add feature information.
"""
feature_names = read_features_from_staged()
if feature_names:
typer.echo(f"Features in staging area: {feature_names}")
write_staged_featureset(feature_names)
else:
typer.echo("No features found in staging area.", err=True)


def read_features_from_staged(type: str = "Union") -> list[str]:
"""
Retrieve the features from the current staging area.

Keyword Arguments:
type -- Can be Union or Intersection. Describes how multiple features will be combined (default: {"Union"})

Returns:
List of features.
"""
typer.echo("Using staged files")

staged_files = get_files_by_git_change().get("staged_files", [])
feature_sets = [set(get_features_for_file(f)) for f in staged_files]

if not feature_sets:
return []

if type == "Union":
combined_features = set.union(*feature_sets)
elif type == "Intersection":
combined_features = set.intersection(*feature_sets)
else:
raise ValueError(
"Invalid type specified. Use 'Union' or 'Intersection'."
)

return list(combined_features)


def stage_files(selected_files: list[str]) -> bool:
"""
Expand Down
56 changes: 56 additions & 0 deletions git_tool/ci/subcommands/feature_add_from_staged.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import typer

from git_tool.feature_data.git_status_per_feature import (
get_features_for_file,
get_files_by_git_change,
)
from git_tool.feature_data.models_and_context.feature_state import (
reset_staged_featureset,
write_staged_featureset,
)


app = typer.Typer()


@app.command(name="add-from-staged", help="Associate staged files with features.")
def features_from_staging_area():
"""
Use the staged files to add feature information.
"""
feature_names = read_features_from_staged()
if feature_names:
typer.echo(f"Features in staging area: {feature_names}")
write_staged_featureset(feature_names)
else:
typer.echo("No features found in staging area.", err=True)


def read_features_from_staged(type: str = "Union") -> list[str]:
"""
Retrieve the features from the current staging area.

Keyword Arguments:
type -- Can be Union or Intersection. Describes how multiple features will be combined (default: {"Union"})

Returns:
List of features.
"""
typer.echo("Using staged files")

staged_files = get_files_by_git_change().get("staged_files", [])
feature_sets = [set(get_features_for_file(f)) for f in staged_files]

if not feature_sets:
return []

if type == "Union":
combined_features = set.union(*feature_sets)
elif type == "Intersection":
combined_features = set.intersection(*feature_sets)
else:
raise ValueError(
"Invalid type specified. Use 'Union' or 'Intersection'."
)

return list(combined_features)
2 changes: 1 addition & 1 deletion git_tool/ci/subcommands/feature_blame.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def print_feature_blame_output(
typer.echo(f"{feature:<15} {i:>4} {line.strip()}")


@app.command(no_args_is_help=True, name=None)
@app.command(help="Display features associated with file lines.", no_args_is_help=True, name=None)
def feature_blame(
filename: str = typer.Argument(
..., help="The file to display feature blame for."
Expand Down
2 changes: 1 addition & 1 deletion git_tool/ci/subcommands/feature_commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

@app.command(
name="commit",
help="Associate an existing commit with one or more features",
help="Associate an existing commit with one or more features.",
no_args_is_help=True,
)
def feature_commit(
Expand Down
35 changes: 5 additions & 30 deletions git_tool/ci/subcommands/feature_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,14 @@
get_files_for_commit,
)
from git_tool.feature_data.git_status_per_feature import get_commits_for_feature
from git_tool.feature_data.read_feature_data.parse_data import (
_get_feature_uuids,
)


def print_list_w_indent(stuff: list, indent: int = 1) -> None:
for item in stuff:
typer.echo("\t" * indent + item)


app = typer.Typer(
help="Displaying feature information for the entire git repo",
no_args_is_help=True,
)

info_app = typer.Typer(
no_args_is_help=True, help="Inspect feature details. This includes "
)
# app.add_typer(info_app, name="info")
# app.add_typer(currently_staged_app, name="currently-staged")
app = typer.Typer(help="Displaying feature information for the entire git repo", no_args_is_help=True)


# TODO sollte zu git feature-status
Expand All @@ -40,7 +28,7 @@ def print_list_w_indent(stuff: list, indent: int = 1) -> None:
# return


@app.command(name="feature", help="Show feature-specific information.")
@app.command(name="info")
def inspect_feature(
feature: str = typer.Argument(..., help="Inspect a particular feature"),
authors: bool = typer.Option(
Expand Down Expand Up @@ -70,7 +58,7 @@ def inspect_feature(
commit_ids = []
typer.echo(f"No commit-ids for feature {feature} found")
if branches:
typer.echo(f"Branches (* indicates current branch)")
typer.echo("Branches (* indicates current branch)")
branches = set(
[
branch
Expand All @@ -80,11 +68,11 @@ def inspect_feature(
)
print_list_w_indent(branches)
if authors:
typer.echo(f"Authors")
typer.echo("Authors")
authors = set([get_author_for_commit(c) for c in commit_ids])
print_list_w_indent(authors)
if files:
typer.echo(f"Files")
typer.echo("Files")
files = set(
file for c in commit_ids for file in get_files_for_commit(c)
)
Expand Down Expand Up @@ -146,18 +134,5 @@ def inspect_feature(
)


@app.command(
name="all",
help="List all available features in the project. \
Use these names with 'git feature-info <feature>' to inspect details.",
)
def all_feature_info():
"""
Inspects feature information.
"""
typer.echo("All Features")
print_list_w_indent(_get_feature_uuids())


if __name__ == "__main__":
app()
22 changes: 22 additions & 0 deletions git_tool/ci/subcommands/feature_info_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import typer

from git_tool.feature_data.read_feature_data.parse_data import (
_get_feature_uuids,
)


app = typer.Typer()


@app.command(name="info-all")
def all_feature_info():
"""
Inspects feature information.
"""
typer.echo("All Features")
print_list_w_indent(_get_feature_uuids())


def print_list_w_indent(stuff: list, indent: int = 1) -> None:
for item in stuff:
typer.echo("\t" * indent + item)
8 changes: 3 additions & 5 deletions git_tool/ci/subcommands/feature_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@
)


@app.command(
help="Displays the current status of files in the working directory, showing staged, unstaged, and untracked changes along with their associated features. \
Files without associated features will be highlighted, and suggestions for adding features will be provided.",
)
@app.command(name="status")
def feature_status(
help: bool = typer.Option(
None, "--help", "-h", is_eager=True, help="Show this message and exit."
)
):
"""
Displays unstaged and staged changes with associated features.
Displays the current status of files in the working directory, showing staged, unstaged, and untracked changes along with their associated features.
Files without associated features will be highlighted, and suggestions for adding features will be provided.
"""
if help:
typer.echo(app.rich_help_panel)
Expand Down
13 changes: 3 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[project]
name = "git_tool"
authors = [{ name = "Tabea Röthemeyer", email = "tabea.roethemeyer@rub.de" }]
authors = [{ name = "Tabea Röthemeyer", email = "tabea.roethemeyer@rub.de" }, { name = "Kim Nguyen", email = "ho.nguyen@rub.de"}]
license = { file = "LICENSE" }
description = "Support feature-oriented development workflows with git"
readme = "README.md"
version = "1.0.10"
version = "1.0.11"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
Expand All @@ -21,14 +21,7 @@ dependencies = [
]

[project.scripts]
git-feature-status = "git_tool.ci.subcommands.feature_status:app"
git-feature-info = "git_tool.ci.subcommands.feature_info:app"
git-feature-add = "git_tool.ci.subcommands.feature_add:app"
git-feature-blame = "git_tool.ci.subcommands.feature_blame:app"
git-feature-commit = "git_tool.ci.subcommands.feature_commit:app"
git-feature-commit-msg = "git_tool.ci.subcommands.feature_commit_msg:app"
git-feature-pre-commit = "git_tool.ci.subcommands.feature_pre_commit:app"
git-feature-commits = "git_tool.ci.subcommands.feature_commits:app"
git-feature = "git_tool.__main__.py:app"

[build-system]
requires = ["hatchling"]
Expand Down