diff --git a/git_tool/__main__.py b/git_tool/__main__.py index 687f249..738100b 100644 --- a/git_tool/__main__.py +++ b/git_tool/__main__.py @@ -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() diff --git a/git_tool/ci/subcommands/feature_add.py b/git_tool/ci/subcommands/feature_add.py index 62efe6c..26e65f4 100644 --- a/git_tool/ci/subcommands/feature_add.py +++ b/git_tool/ci/subcommands/feature_add.py @@ -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" @@ -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: """ diff --git a/git_tool/ci/subcommands/feature_add_from_staged.py b/git_tool/ci/subcommands/feature_add_from_staged.py new file mode 100644 index 0000000..66f528b --- /dev/null +++ b/git_tool/ci/subcommands/feature_add_from_staged.py @@ -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) \ No newline at end of file diff --git a/git_tool/ci/subcommands/feature_blame.py b/git_tool/ci/subcommands/feature_blame.py index 423506d..fbd3e90 100644 --- a/git_tool/ci/subcommands/feature_blame.py +++ b/git_tool/ci/subcommands/feature_blame.py @@ -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." diff --git a/git_tool/ci/subcommands/feature_commit.py b/git_tool/ci/subcommands/feature_commit.py index fbd6493..2e142eb 100644 --- a/git_tool/ci/subcommands/feature_commit.py +++ b/git_tool/ci/subcommands/feature_commit.py @@ -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( diff --git a/git_tool/ci/subcommands/feature_info.py b/git_tool/ci/subcommands/feature_info.py index 879908f..6cae262 100644 --- a/git_tool/ci/subcommands/feature_info.py +++ b/git_tool/ci/subcommands/feature_info.py @@ -10,9 +10,6 @@ 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: @@ -20,16 +17,7 @@ def print_list_w_indent(stuff: list, indent: int = 1) -> None: 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 @@ -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( @@ -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 @@ -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) ) @@ -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 ' 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() diff --git a/git_tool/ci/subcommands/feature_info_all.py b/git_tool/ci/subcommands/feature_info_all.py new file mode 100644 index 0000000..4bd86c5 --- /dev/null +++ b/git_tool/ci/subcommands/feature_info_all.py @@ -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) \ No newline at end of file diff --git a/git_tool/ci/subcommands/feature_status.py b/git_tool/ci/subcommands/feature_status.py index b675503..7800182 100644 --- a/git_tool/ci/subcommands/feature_status.py +++ b/git_tool/ci/subcommands/feature_status.py @@ -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) diff --git a/pyproject.toml b/pyproject.toml index af19bd0..a5134ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", @@ -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"]