diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 0000000..507640b --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,22 @@ +name: Tests git-auto-commit + +on: + pull_request: + branches: [main] + +jobs: + go_check: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: '1.23.0' + + - name: Run tests + run: | + make test \ No newline at end of file diff --git a/Help/www/index.html b/Help/www/index.html index d12ae38..d5b85ff 100644 --- a/Help/www/index.html +++ b/Help/www/index.html @@ -1,182 +1,143 @@ - - - - Git Auto-Commit - The Future Industries - - - - - - - - - - - - - - - - -
-

Git auto-commit - automatic commit generation tool

+ + + + Git Auto-Commit - The Future Industries + + + + + + + + + + -

- Git Auto-Commit is an extension for the Git version control - system designed to automatically generate meaningful and - context-sensitive commit messages based on changes made to the - codebase. The tool simplifies developers' workflows by allowing - them to focus on the content of edits rather than on the - formulation of descriptions for commits. -

+ + + +
+

Git Auto-Commit — Automatic Commit Generation Tool

-

- The development is conducted as an open source project and is - distributed under the MIT license (or other compatible - licensing, depending on the implementation). Git Auto-Commit can - be integrated into CI/CD pipelines, hook scripts, or used - manually via the command line. -

+

+ Git Auto-Commit is an extension for Git designed to automatically generate meaningful, context-aware commit messages based on your code changes. + This tool streamlines the development workflow by letting you focus on writing code instead of manually crafting commit messages. +

-

Main features:

- +

+ Developed as an open-source project under the MIT license (or compatible licensing), Git Auto-Commit can be integrated into CI/CD pipelines, hook scripts, or used manually via the command line. +

-

Install

-

- If you're on Windows
- Go to the root of the project and run the command: -

-
-iex ((New-Object Net.WebClient).DownloadString('https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-windows-auto-commit.ps1?raw=true'))
+

Main Features

+ -

- If you're on Linux
- Go to the root of the project and run the command: -

-
-echo Y | bash <(curl -fsSL https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-linux-auto-commit.sh?raw=true)
+

Install

-

- If you're on MacOS
- Go to the root of the project and run the command: -

-
-echo Y | curl -fsSL https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-macos-auto-commit.sh?raw=true | bash
+

Windows

+
iex ((New-Object Net.WebClient).DownloadString('https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-windows-auto-commit.ps1?raw=true'))
-

Setting up

-

Launch

-

- Everything is ready now, after making changes to the code, just - run: -

+

Linux

+
echo Y | bash <(curl -fsSL https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-linux-auto-commit.sh?raw=true)
-

1 Option

-
+        

macOS

+
echo Y | curl -fsSL https://github.com/thefuture-industries/git-auto-commit/blob/main/scripts/install-macos-auto-commit.sh?raw=true | bash
+ +

Setting Up

+

Launch

+

Once installed, you can start committing automatically:

+ +
Option 1 — Manual Commit
+
 git add .
 git auto
-git push
+git push +
+ +
Option 2 — Git Auto Commands
+
+git auto -w   # Watch mode: automatically commits when changes are detected
+git auto -v   # View current auto-commit version
+git auto -u   # Update to the latest auto-commit version
+        
-

2 Commands

-
-git auto -w   # Commit observer: you don't have to think and write anymore, `git auto -w` will figure it out and commit for you!
-git auto -v   # Viewing the current version of auto-commit
-git auto -u   # Upgrade to the new auto-commit version
+
-
- Distributed under the MIT License • © 2025 The Future - Industries -
-
+ +
- - - + + + \ No newline at end of file diff --git a/README.md b/README.md index 7e6aea3..a6f671a 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,26 @@ git push - 2 Commands +#### Launching in monitoring mode + +Comit observer, you dont have to think and write more `git auto` -w (--watch) will figure it out when to make a comit and commit it yourself! + +```bash +git auto -w +``` + +#### Viewing the current version + +Viewing the current version of auto-commit + +```bash +git auto -v +``` + +#### Upgrade to a new version + +Upgrade to the new auto-commit version + ```bash -git auto -w - Comit observer, you dont have to think and write more `git auto` -w (--watch) will figure it out when to make a comit and commit it yourself! -git auto -v - Viewing the current version of auto-commit -git auto -u - Upgrade to the new auto-commit version +git auto -u ``` diff --git a/infra/constants/expanding-notation-folders.go b/infra/constants/expanding-notation-folders.go index 771c917..f009ea9 100644 --- a/infra/constants/expanding-notation-folders.go +++ b/infra/constants/expanding-notation-folders.go @@ -105,4 +105,70 @@ var EXPANDING_NOTATION_FOLDERS = map[string]string{ ".prettier": "Prettier configuration files", ".stylelint": "Stylelint configuration files", ".scripts": "Custom shell or utility scripts", + "examples_data": "example datasets", + "benchmark": "benchmark tests", + "perf": "performance tests", + "patches": "patch files", + "hooks": "Git hooks", + "extensions": "code extensions or plugins", + "plugins": "application plugins", + "adapters": "adapter components", + "drivers": "hardware or software drivers", + "manifests": "deployment manifests", + "policies": "security or compliance policies", + "secrets": "secret files", + "keys": "encryption or API keys", + "certs": "SSL/TLS certificates", + "backups": "backup files", + "restore": "restore scripts", + "env": "environment configuration files", + "pipelines": "CI/CD pipelines", + "jobs": "scheduled jobs", + "tasks": "task definitions", + "workflows": "workflow definitions", + "automation": "automation scripts", + "maintenance": "maintenance scripts", + "support": "supporting documents", + "guides": "user or developer guides", + "references": "reference materials", + "diagrams": "architecture diagrams", + "schemasql": "SQL schema definitions", + "etl": "ETL scripts and configs", + "ml": "machine learning models", + "ai": "artificial intelligence code", + "nn": "neural network models", + "dl": "deep learning models", + "cv": "computer vision code", + "nlp": "natural language processing code", + "speech": "speech recognition code", + "bot": "bot scripts", + "scraper": "web scraper scripts", + "crawler": "web crawler scripts", + "feeds": "data feed scripts", + "api_clients": "API client implementations", + "rest": "REST API code", + "graphql": "GraphQL API code", + "soap": "SOAP API code", + "rpc": "RPC service code", + "serverless": "serverless functions", + "lambda": "AWS Lambda functions", + "cloud": "cloud service configs", + "gcp": "Google Cloud Platform configs", + "azure": "Azure cloud configs", + "aws": "Amazon Web Services configs", + "bff": "backend-for-frontend services", + "queue": "message queue handlers", + "kafka": "Kafka event handlers", + "rabbitmq": "RabbitMQ consumers/producers", + "redis": "Redis cache configs", + "memcached": "Memcached configs", + "search": "search service configs", + "elasticsearch": "Elasticsearch configs", + "solr": "Apache Solr configs", + "prometheus": "Prometheus monitoring configs", + "grafana": "Grafana dashboards", + "alertmanager": "Alertmanager configs", + "jaeger": "Jaeger tracing configs", + "opentelemetry": "OpenTelemetry configs", + "tracing": "distributed tracing configs", } diff --git a/pkg/cli/watcher.go b/pkg/cli/watcher.go index 83528a2..dd315da 100644 --- a/pkg/cli/watcher.go +++ b/pkg/cli/watcher.go @@ -48,6 +48,9 @@ func (cli *CLI) Watch(path string) { os.Exit(0) }() + var lastChange time.Time + var commitScheduled bool + for { select { case event := <-watcher.Events: @@ -62,6 +65,14 @@ func (cli *CLI) Watch(path string) { continue } + lastChange = time.Now() + commitScheduled = true + } + case err := <-watcher.Errors: + logger.ErrorLogger(err) + + default: + if commitScheduled && time.Since(lastChange) >= time.Minute { if err := exec.Command("git", "add", ".").Run(); err != nil { logger.ErrorLogger(err) return @@ -84,14 +95,15 @@ func (cli *CLI) Watch(path string) { return } - if uint16(len(parser)) >= constants.MAX_COMMIT_LENGTH_WATCHER { - if err := cli.Git.Commit(parser); err != nil { - logger.ErrorLogger(err) - } + if err := cli.Git.Commit(parser); err != nil { + logger.ErrorLogger(err) } + + commitScheduled = false } - case err := <-watcher.Errors: - logger.ErrorLogger(err) + + time.Sleep(650 * time.Millisecond) + } time.Sleep(constants.COMMIT_TIME) diff --git a/pkg/code/code.go b/pkg/code/code.go index 84db121..1577395 100644 --- a/pkg/code/code.go +++ b/pkg/code/code.go @@ -1,7 +1,6 @@ package code import ( - "bufio" "git-auto-commit/infra/constants" "os/exec" "path/filepath" @@ -12,32 +11,32 @@ var ExecCommand = exec.Command func (c *Code) FormattedCode(files []string) (string, error) { args := append([]string{"diff", "--cached", "--name-status"}, files...) - cmd := ExecCommand("git", args...) - stdout, err := cmd.StdoutPipe() + stdout, err := ExecCommand("git", args...).Output() if err != nil { return "", err } - if err := cmd.Start(); err != nil { - return "", err - } - var added, modified, deleted []string - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) + lines := strings.Split(strings.TrimSpace(string(stdout)), "\n") + for _, line := range lines { + line = strings.TrimSpace(line) if line == "" { continue } - parts := strings.Fields(line) - if len(parts) != 2 { - continue + sep := strings.IndexByte(line, '\t') + if sep == -1 { + sep = strings.IndexByte(line, ' ') + if sep == -1 { + continue + } } - status, file := parts[0], parts[1] + status := strings.TrimSpace(line[:sep]) + file := strings.TrimSpace(line[sep+1:]) + switch status { case constants.NameStatus_Added: added = append(added, file) @@ -51,14 +50,6 @@ func (c *Code) FormattedCode(files []string) (string, error) { } } - if err := scanner.Err(); err != nil { - return "", err - } - - if err := cmd.Wait(); err != nil { - return "", err - } - msg := c.build(added, modified, deleted) return c.WithTag(files, msg, added, modified, deleted), nil } @@ -87,33 +78,44 @@ func (c *Code) build(added, modified, deleted []string) string { } func (c *Code) summarize(files []string) string { - folders := map[string]struct{}{} + seen := make(map[string]struct{}, len(files)) + names := make([]string, 0, len(files)) + for _, file := range files { - directory := strings.Split(filepath.ToSlash(file), "/")[0] + var dir string - if directory == "." || directory == "" { - directory = strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) + if slash := strings.IndexByte(file, '/'); slash != -1 { + dir = file[:slash] + } else { + dir = strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) } - folders[directory] = struct{}{} - } + if dir == "." || dir == "" { + dir = strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) + } - names := make([]string, 0, len(folders)) - for name := range folders { - if desc, ok := constants.EXPANDING_NOTATION_FOLDERS[name]; ok { - names = append(names, desc) - } else { - names = append(names, name) + if _, exists := seen[dir]; !exists { + seen[dir] = struct{}{} + if desc, ok := constants.EXPANDING_NOTATION_FOLDERS[dir]; ok { + names = append(names, desc) + } else { + names = append(names, dir) + } } } - if len(names) == 1 { + switch len(names) { + case 0: + return "" + + case 1: return names[0] - } - if len(names) == 2 { + case 2: return names[0] + " and " + names[1] - } - return strings.Join(names[:len(names)-1], ", ") + " and " + names[len(names)-1] + default: + return strings.Join(names[:len(names)-1], ", ") + " and " + names[len(names)-1] + + } } diff --git a/tests/code/impl-mod-del/implemented_modified_deleted_test.go b/tests/code/impl-mod-del/implemented_modified_deleted_test.go new file mode 100644 index 0000000..4316b1e --- /dev/null +++ b/tests/code/impl-mod-del/implemented_modified_deleted_test.go @@ -0,0 +1,41 @@ +package implmoddel + +import ( + "fmt" + "git-auto-commit/pkg/code" + "git-auto-commit/tests" + "os/exec" + "strings" + "testing" +) + +const implementeModifieDeleteExpectedTest string = "[feat] Implemented source code files, updated public reusable packages, removed error" + +func TestImplementedModifiedDeleted(t *testing.T) { + gitOutput := ` + M pkg/modified.mod + A src/implemented.impl + D error/deleted.del + ` + + code.ExecCommand = func(name string, args ...string) *exec.Cmd { + return tests.FakeExecCommand(gitOutput) + } + defer func() { + code.ExecCommand = exec.Command + }() + + c := &code.Code{} + + files := []string{"src/implemented.impl", "pkg/modified.mod", "error/deleted.del"} + msg, err := c.FormattedCode(files) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if !strings.EqualFold(strings.TrimSpace(msg), strings.TrimSpace(implementeModifieDeleteExpectedTest)) { + t.Errorf("Expected commit message:\n%q\nGot:\n%q", implementeModifieDeleteExpectedTest, msg) + } + + fmt.Println("==> Formatted commit message:", msg) +}