├── .commitlog.release ├── .github └── workflows │ ├── changelog.yml │ ├── create-binaries.yml │ ├── docs.yml │ └── test.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets └── commitlog.png ├── commands ├── commitlog.go └── release.go ├── docs ├── api.md ├── download.md ├── index.md ├── manual.md └── styles.css ├── go.mod ├── go.sum ├── lib ├── commands.go └── commits.go ├── main.go ├── pkg ├── generator.go └── releaser.go └── scripts ├── cross-compile.sh ├── generate-docs.sh └── get-release-urls.sh /.commitlog.release: -------------------------------------------------------------------------------- 1 | v3.0.0 -------------------------------------------------------------------------------- /.github/workflows/changelog.yml: -------------------------------------------------------------------------------- 1 | name: Changelogs 2 | 3 | on: 4 | push: 5 | tags: "*" 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | with: 14 | fetch-depth: 0 15 | - name: Generate Change Log 16 | id: generate_log 17 | run: | 18 | curl -sSL https://goblin.run/github.com/barelyhuman/commitlog/v3@v3 | sh 19 | commitlog g > CHANGELOG.md 20 | - uses: ncipollo/release-action@v1 21 | with: 22 | bodyFile: "CHANGELOG.md" 23 | token: ${{ secrets.GH_TOKEN }} 24 | -------------------------------------------------------------------------------- /.github/workflows/create-binaries.yml: -------------------------------------------------------------------------------- 1 | name: Binary Builds 2 | 3 | on: 4 | release: 5 | types: 6 | - created 7 | 8 | jobs: 9 | releases-matrix: 10 | name: Release Go Binary 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | goos: [linux, windows, darwin] 15 | goarch: ["386", amd64, arm64] 16 | exclude: 17 | - goarch: "386" 18 | goos: darwin 19 | - goarch: arm64 20 | goos: windows 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: wangyoucao577/go-release-action@v1 24 | with: 25 | github_token: ${{ secrets.GH_TOKEN }} 26 | goos: ${{ matrix.goos }} 27 | goarch: ${{ matrix.goarch }} 28 | ldflags: "-w -s" 29 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | on: [push] 3 | jobs: 4 | build-docs: 5 | concurrency: ci-${{ github.ref }} 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout 🛎️ 9 | uses: actions/checkout@v3 10 | 11 | - name: Install and Build 12 | run: ./scripts/generate-docs.sh 13 | 14 | - name: Deploy 🚀 15 | uses: JamesIves/github-pages-deploy-action@v4.3.3 16 | with: 17 | token: ${{ secrets.GH_TOKEN }} 18 | branch: gh-pages 19 | folder: dist 20 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | build_and_test: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - name: Set up Go 14 | uses: actions/setup-go@v2 15 | with: 16 | go-version: 1.16 17 | 18 | - name: Build 19 | run: go build -v ./... 20 | 21 | - name: Test 22 | run: go test -v ./... 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | ./commitlog 3 | .DS_Store 4 | dist 5 | commitlog 6 | lab 7 | api_urls.json 8 | /bin -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | ahoy@barelyhuman.dev. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | You are free to raise PR's for any kind of improvements and or feature additions, they'll be added to the repository accordingly, you can also fork up your own version as the repo will remain MIT licensed 2 | 3 | ## Dev Guidelines 4 | - Fork the Repo 5 | - Make your changes (use `git pull --rebase` when working with others to avoid creating un-needed merge commits ) 6 | - Raise a PR 7 | - Your changes will then be reviewed and merged into a test pr-#id-rebase branch for testing 8 | and then merged into `main` if everything goes through 9 | 10 | ## Pull Request and Commit Guidelines 11 | - Commitlog is based off of commit standards where the commit message specifies what 12 | kind of commit it is, make sure your commits follow the same. 13 | - The PR doesn't need to have detailed explanation but a small pointer of what each commit does should be fine, 14 | on the other hand you could use commitlog to generate the hash and changes for your PR 15 | 16 | --- 17 | Finally, 18 | **Maintain a healthy and friendly environment in all the threads (discussions, issue thread, PR Threads)** 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Reaper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

commits to changelogs

4 | 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/barelyhuman/commitlog)](https://goreportcard.com/report/github.com/barelyhuman/commitlog) 6 | 7 | ## Philosophy 8 | 9 | - Work on all major operating systems 10 | - Not platform dependent, not tied to Github, Gitlab, or anything. It's just markdown. 11 | - Ability to generate change logs between version tags 12 | - Handle release versioning of the project 13 | - Stay small 14 | 15 | ## Installation 16 | 17 | 18 | ### Using [goblin.run](https://goblin.run) 19 | ```sh 20 | ; curl -sfL https://goblin.run/github.com/barelyhuman/commitlog/v3 | sh 21 | ``` 22 | 23 | ### go 24 | If you have go installed, you can use the below command 25 | 26 | ```sh 27 | go install github.com/barelyhuman/commitlog/v3@latest 28 | ``` 29 | 30 | ## Why 31 | 32 | Every language has it's own isolated version of a tool like this, for someone who works with multiple languages, it's easier to 33 | have the same tool working everywhere, without having to setup something get it working. There's an even tighter scoped version of this, [nimclog](https://github.com/barelyhuman/nimclog). 34 | 35 | The point of the tool is not to create super descriptive changelogs for you but to help your changelogs have enough information for you as a developer to be able to write proper changelogs while having references to the changes in one place. 36 | 37 | ## Documentation 38 | 39 | The documentation can be read from the `docs` folder of the repository, or on the [website](https://barelyhuman.github.io/commitlog) 40 | 41 | ## License 42 | 43 | [MIT](/LICENSE) 44 | -------------------------------------------------------------------------------- /assets/commitlog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barelyhuman/commitlog/4b7ea89c38ae2c0728f1f7ec263eb5d6e499a082/assets/commitlog.png -------------------------------------------------------------------------------- /commands/commitlog.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "github.com/barelyhuman/commitlog/v3/pkg" 5 | "github.com/urfave/cli/v2" 6 | ) 7 | 8 | func Commitlog(c *cli.Context) (err error) { 9 | path := c.String("path") 10 | addPromo := c.Bool("promo") 11 | out := c.String("out") 12 | stdio := c.Bool("stdio") 13 | startRef := c.String("start") 14 | endRef := c.String("end") 15 | categories := c.String("categories") 16 | 17 | gOptions := []pkg.GeneratorConfigMod{} 18 | 19 | if addPromo { 20 | gOptions = append(gOptions, 21 | pkg.WithPromo(), 22 | ) 23 | } 24 | 25 | // either write to a file or to the stdio with true by default 26 | if len(out) > 0 { 27 | gOptions = append(gOptions, 28 | pkg.WithOutputToFile(out), 29 | ) 30 | } else if stdio { 31 | gOptions = append(gOptions, 32 | pkg.WithOutputToStdio(), 33 | ) 34 | } 35 | 36 | if len(startRef) > 0 { 37 | gOptions = append(gOptions, 38 | pkg.WithStartReference(startRef), 39 | ) 40 | } 41 | 42 | if len(endRef) > 0 { 43 | gOptions = append(gOptions, 44 | pkg.WithEndReference(endRef), 45 | ) 46 | } 47 | 48 | if len(categories) > 0 { 49 | gOptions = append(gOptions, 50 | pkg.WithCategories(categories), 51 | ) 52 | } 53 | 54 | generator := pkg.CreateGenerator(path, 55 | gOptions...) 56 | 57 | err = generator.ReadCommmits() 58 | 59 | if err != nil { 60 | return err 61 | } 62 | 63 | err = generator.Classify() 64 | 65 | if err != nil { 66 | return err 67 | } 68 | 69 | return generator.Generate() 70 | } 71 | -------------------------------------------------------------------------------- /commands/release.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "path" 8 | 9 | "github.com/barelyhuman/commitlog/v3/lib" 10 | "github.com/barelyhuman/commitlog/v3/pkg" 11 | "github.com/go-git/go-git/v5" 12 | "github.com/go-git/go-git/v5/plumbing" 13 | "github.com/urfave/cli/v2" 14 | ) 15 | 16 | func Release(c *cli.Context) (err error) { 17 | 18 | fileDir := c.String("path") 19 | filePath := path.Join(fileDir, ".commitlog.release") 20 | 21 | if !(c.Bool("init") || c.Bool("major") || c.Bool("minor") || c.Bool("patch") || c.Bool("pre")) { 22 | err = fmt.Errorf("[commitlog] need at least one increment flag to move ahead") 23 | return 24 | } 25 | 26 | if c.Bool("init") { 27 | _, err = os.Stat(filePath) 28 | if os.IsNotExist(err) { 29 | err = nil 30 | os.WriteFile(filePath, []byte("v0.0.0"), os.ModePerm) 31 | fmt.Println("[commitlog] Initialized commitlog release") 32 | } else { 33 | err = fmt.Errorf(".commitlog.release already exists, cannot override") 34 | } 35 | return 36 | } 37 | 38 | _, err = os.Stat(filePath) 39 | 40 | if os.IsNotExist(err) { 41 | err = fmt.Errorf("couldn't find the release file, please run the `--init` flag first") 42 | return 43 | } 44 | 45 | fileData, err := os.ReadFile(filePath) 46 | 47 | if err != nil { 48 | err = fmt.Errorf("error reading the version file: %v", err) 49 | return err 50 | } 51 | 52 | versionString := string(fileData) 53 | 54 | releaserOpts := []pkg.ReleaserMod{ 55 | // add in the pre-tag, 56 | // will be used only if the pre flag 57 | // is true 58 | pkg.WithPreTag(c.String("pre-tag")), 59 | } 60 | 61 | if c.Bool("major") { 62 | releaserOpts = append(releaserOpts, pkg.WithClearPrerelease(), pkg.WithMajorIncrement(), pkg.WithMinorReset(), pkg.WithPatchReset()) 63 | } 64 | 65 | if c.Bool("minor") { 66 | releaserOpts = append(releaserOpts, pkg.WithClearPrerelease(), pkg.WithMinorIncrement(), pkg.WithPatchReset()) 67 | } 68 | 69 | if c.Bool("patch") { 70 | releaserOpts = append(releaserOpts, pkg.WithClearPrerelease(), pkg.WithPatchIncrement()) 71 | } 72 | 73 | if c.Bool("pre") { 74 | releaserOpts = append(releaserOpts, pkg.WithPrereleaseIncrement()) 75 | } 76 | 77 | releaser, err := pkg.CreateNewReleaser(versionString, releaserOpts...) 78 | 79 | if err != nil { 80 | return err 81 | } 82 | 83 | err = os.WriteFile(filePath, []byte(releaser.String()), os.ModePerm) 84 | if err != nil { 85 | return 86 | } 87 | 88 | var gitRepo *git.Repository 89 | var toTagHash plumbing.Hash 90 | var repoWt *git.Worktree 91 | 92 | if c.Bool("commit") || c.Bool("push") { 93 | gitRepo, err = git.PlainOpen(c.String("path")) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | repoWt, err = gitRepo.Worktree() 99 | 100 | if err != nil { 101 | return err 102 | } 103 | } 104 | 105 | if c.Bool("commit") { 106 | msg := "chore: " + releaser.String() 107 | repoWt.Add(filePath) 108 | toTagHash, err = repoWt.Commit(msg, &git.CommitOptions{}) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | _, err = gitRepo.CreateTag(releaser.String(), toTagHash, &git.CreateTagOptions{ 114 | Message: msg, 115 | }) 116 | if err != nil { 117 | err = fmt.Errorf("looks like there was error while creating a tag for the version commit, please try again or create a tag manually: %v", err) 118 | return err 119 | } 120 | } 121 | 122 | if c.Bool("push") { 123 | _, err = repoWt.Status() 124 | if err != nil { 125 | return err 126 | } 127 | 128 | cmd := exec.Command("git", "push") 129 | cmd.Dir = fileDir 130 | err = lib.Command(cmd) 131 | 132 | if err != nil { 133 | return err 134 | } 135 | 136 | cmd = exec.Command("git", "push", "--tags") 137 | cmd.Dir = fileDir 138 | 139 | if err = lib.Command(cmd); err != nil { 140 | return err 141 | } 142 | } 143 | 144 | return err 145 | } 146 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | commitlog | manual 4 | 5 | 6 | 7 | 8 | ### [commitlog](/) 9 | 10 | [Home](/) [Manual](/manual) [Download](/download) [API](/api) 11 | 12 | # API 13 | 14 | ### General Guide 15 | 16 | commitlog also comes as a pkg that you could reuse to modify the behaviour of 17 | the commands and this is very limited at the moment since I'm still working on 18 | the best way to get plugins to work with the original CLI instead of having to 19 | write your own version of commitlog. 20 | 21 | The pkg contains the 2 base command's creators and behaviour modifiers, or more 22 | commonly known as the golang options pattern. 23 | 24 | Briefly put, You have one function that takes in unlimited amount of functions 25 | as parameter with each of these parameter functions being able to modify the 26 | behaviour of the returned instance. 27 | 28 | Easy way to explain this is with an example of the `releaser` API 29 | 30 | ```go 31 | package main 32 | 33 | import ( 34 | "log" 35 | 36 | "github.com/barelyhuman/commitlog/v3/pkg" 37 | ) 38 | 39 | func main() { 40 | versionString := "v0.0.1" 41 | releaser, _ := pkg.CreateNewReleaser( 42 | versionString, 43 | pkg.WithMajorIncrement(), 44 | ) 45 | 46 | log.Println(releaser.String()) 47 | 48 | } 49 | ``` 50 | 51 | here the `pkg.CreateNewReleaser` takes in one mandatory value which is the 52 | `versionString` and the 2nd parameter is optional here. 53 | 54 | Though, since we wish for the releaser to have a custom behaviour everytime the 55 | flags change, instead of writing entire functionalities inside various releaser 56 | functions, which would look like so 57 | 58 | ```go 59 | releaser.IncrementMajor() 60 | releaser.IncrementMinor() 61 | ``` 62 | 63 | I'd be unable to expose the builders / option functions out to the public for 64 | them to write custom behaviours that work directly with the `struct` being used 65 | by commitlog itself and instead you'd be writing wrappers around existing 66 | functions. Thus, adding another layer of abstraction which isn't needed for 67 | something that wants to be extended. 68 | 69 | This approach gives me the ability to expose a selected few properties for you 70 | to modify while writing your own builder/option function. 71 | 72 | The only pointer functions that releaser has is the one's that'll help with 73 | printing or identifying the final version's state. 74 | 75 | Since, you now know how the API is written, the go doc for this module should be 76 | able to help you with the remaining. 77 | 78 | [godoc↗](https://pkg.go.dev/github.com/barelyhuman/commitlog) 79 | 80 | > **Note**: if the go doc still hasn't been generated for v2.0.0, please go 81 | > through the source code to help you with the implementation details 82 | -------------------------------------------------------------------------------- /docs/download.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | commitlog | downloads 4 | 5 | 6 | 7 | 8 | ### [commitlog](/) 9 | 10 | [Home](/) [Manual](/manual) [Download](/download) [API](/api) 11 | 12 | #### Downloads 13 | 14 | [commitlog-v3.0.0-darwin-amd64.tar.gz](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-darwin-amd64.tar.gz) 15 | [commitlog-v3.0.0-darwin-amd64.tar.gz.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-darwin-amd64.tar.gz.md5) 16 | [commitlog-v3.0.0-darwin-arm64.tar.gz](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-darwin-arm64.tar.gz) 17 | [commitlog-v3.0.0-darwin-arm64.tar.gz.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-darwin-arm64.tar.gz.md5) 18 | [commitlog-v3.0.0-linux-386.tar.gz](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-386.tar.gz) 19 | [commitlog-v3.0.0-linux-386.tar.gz.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-386.tar.gz.md5) 20 | [commitlog-v3.0.0-linux-amd64.tar.gz](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-amd64.tar.gz) 21 | [commitlog-v3.0.0-linux-amd64.tar.gz.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-amd64.tar.gz.md5) 22 | [commitlog-v3.0.0-linux-arm64.tar.gz](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-arm64.tar.gz) 23 | [commitlog-v3.0.0-linux-arm64.tar.gz.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-linux-arm64.tar.gz.md5) 24 | [commitlog-v3.0.0-windows-386.zip](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-windows-386.zip) 25 | [commitlog-v3.0.0-windows-386.zip.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-windows-386.zip.md5) 26 | [commitlog-v3.0.0-windows-amd64.zip](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-windows-amd64.zip) 27 | [commitlog-v3.0.0-windows-amd64.zip.md5](https://github.com/barelyhuman/commitlog/releases/download/v3.0.0/commitlog-v3.0.0-windows-amd64.zip.md5) 28 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | commitlog 4 | 5 | 6 | 7 | 8 | ### [commitlog](/) 9 | 10 | [Home](/) [Manual](/manual) [Download](/download) [API](/api) 11 | 12 | #### Index 13 | 14 | - [Source](https://github.com/barelyhuman/commitlog) 15 | - [Quick Start](#quick-start) 16 | - [About](#about) 17 | - [Philosophy](#philosophy) 18 | - [Installation](#installation) 19 | - [Manual](/manual) 20 | - [License](#license) 21 | 22 |

Quick Start

23 | 24 | For the one's who already know the tool and wanna get started quickly. 25 | 26 | You can get the CLI in the following ways 27 | 28 | 1. You can get the binaries from the [download section](/download) 29 | 30 | 2. Using `go` 31 | 32 | ```sh 33 | go get -u github.com/barelyhuman/commitlog/v3 34 | # or 35 | go install github.com/barelyhuman/commitlog/v3@latest 36 | ``` 37 | 38 | 3. Using goblin 39 | 40 | ```sh 41 | curl -sf https://goblin.run/github.com/barelyhuman/commitlog/v3 | OUT=commitlog sh 42 | ``` 43 | 44 | Once installed you can just run `commitlog generate` or the shorter version 45 | `commitlog g` to get all the changes between the recent tags. 46 | 47 |

About

48 | 49 |
Philosophy
50 | 51 | **_commitlog_** simply exists because I wasn't able to find a decent enough tool 52 | to do this without being bound to a specific programming language and it's 53 | toolset. The closes one to this is the `git`'s own `shortlog` and `log` commands 54 | 55 | - **Language Agnostic** - No one needs the entire programming toolset or the 56 | language to be setup on the system to be able to just generate logs 57 | 58 | - **Decently Sized** - Not everyone has a powerful system and CI systems are 59 | still very limited in terms of resources since they give you shared spaces and 60 | automating generating this is a common practice so it doesn't make sense for 61 | it to install a runtime worth 100MB to run it. 62 | 63 | The binary itself is around 10-13MB which is fairly big for a tool like this 64 | but this is due to go's nature of embedding the platform runtime with the 65 | binary and this might not be ideal for some and so there's another similar 66 | smaller scoped version [nimclog](https://github.com/barelyhuman/nimclog) which 67 | is in KB's 68 | 69 | - **Flexible** - There are no set standards for how you write commit messages. 70 | Commitlint is a good standard and pretty widely used and also what commitlog 71 | v1 used as the base for categorizing. 72 | 73 | V2 however, doesn't have a set commit category standard, it accepts regex's 74 | that you will categorize your commits for you. 75 | 76 | This is more for experienced developers who have a their own pattern of 77 | writing commits and would like a tool that'd work with their pattern instead 78 | of creating friction 79 | 80 | - **Extensible** - The entire thing is open source and MIT licenses, 81 | specifically for you to be able to fix and add things as needed. Each command 82 | has been kept away from the domain logic to be able to use `commitlog` even as 83 | a library and build your own tool if you wish to, though if there's something 84 | you wish the CLI supported, you are free to open issues and I really like 85 | people helping with the development since that helps keeping the tool alive 86 | longer. 87 | 88 |
Installation
89 | 90 | The installation is pretty straightforwad. You [download](/download) the binary 91 | from the download section of this website or use something like 92 | [goblin](https://goblin.run) to build the binary for your specific 93 | system (rarely needed) since the releases actually accommodate the most used 94 | operating systems and architectures already. 95 | 96 | **Linux/Mac (Unix Systems)** 97 | 98 | Once downloaded, you can use the `install` command on \*nix systems to link the 99 | binary to a location that's already in your PATH variable. 100 | 101 | eg: 102 | 103 | ```bash 104 | # install commitlog from current directory to the /usr/local/bin directory 105 | install $(pwd)/commitlog /usr/local/bin 106 | ``` 107 | 108 | This should give you the ability to use the `commitlog` command anywhere in your 109 | system 110 | 111 | **Windows** 112 | 113 | Similar to the linux setup, you can download the `.exe` file and add it to a 114 | location that your environment path already has. An easier thing to do is to 115 | store the entire thing in your secondary partition and add that location to your 116 | PATH. You can use this resource from Java docs to help you with modifying the 117 | PATH variables 118 | 119 | - [Modifying PATH in Windows](https://www.java.com/en/download/help/path.html) 120 | 121 |

Manual

122 | 123 | [Read Manual →](/manual) 124 | 125 |

License

126 | 127 | commitlog is MIT Licensed and you can read the entire license in the 128 | [source code](https://github.com/barelyhuman/commitlog) 129 | -------------------------------------------------------------------------------- /docs/manual.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | commitlog | manual 4 | 5 | 6 | 7 | 8 | ### [commitlog](/) 9 | 10 | [Home](/) [Manual](/manual) [Download](/download) [API](/api) 11 | 12 | # Manual 13 | 14 | - [Basics](#basics) 15 | - [generate](#generate) 16 | - [release](#release) 17 | - [Advanced](#advanced) 18 | - [Selective Log Ranges](#selective-log-ranges) 19 | - [From a different repo](#from-a-different-repo) 20 | - [Categorize](#categorize) 21 | - [CLI](#cli) 22 | - [API](/api) 23 | 24 |

Basics

25 | 26 | **_`commitlog`_** come with 2 basic functionalities 27 | 28 | - Generating commits as changelogs in markdown 29 | - Managing your version and tags 30 | 31 | Both the above are available as sub commands and we'll go through each one by 32 | one. 33 | 34 | Just running `commitlog` no longer works as it did in v1, you'll need to specify 35 | a sub command to get it working. 36 | 37 | This has been done to keep it simpler to keep arbitrary behaviour to a minimum 38 | 39 |

generate

40 | 41 | The first one is `generate` and in most cases you'll just be using this to 42 | handle generation of commits as a list of markdown notes 43 | 44 | Here's an example of what it'll look like to run the `generate` sub-command 45 | 46 | ```sh 47 | $ commitlog generate 48 | # or 49 | $ commitlog g 50 | ``` 51 | 52 | **Output**: 53 | 54 | ```md 55 | ## All Changes 56 | 87ce3fc76b252908cdd81f9537713f8d67813652 chore: v2.0.0-beta.0 57 | 58 | 09fc85c0d1d52d770bbbf39ac45907103a53d354 refactor: swap go-git for push with exec 59 | 60 | 5bafe9d105298001707c7c816e60d3ef0257a816 fix: tag creation 61 | 62 | 909fd032facdeb4fb7633a4fad82dced28e8de83 chore: swap debugging logger with stderr printer 63 | 64 | ``` 65 | 66 | The behaviour of the `generate` command is like so 67 | 68 | - go through all commits from the current `HEAD` (commit with the `HEAD` 69 | reference) till the last commit or the most recent tagged commit. 70 | - the other case is where if the latest commit is also a tagged commit, it'll 71 | still go till the most recent tagged commit. 72 | 73 | eg: v0.0.2 -> HEAD, v0.0.1 -> SOMEHASH, would give you the commits between 74 | both the tags. 75 | 76 | The default behaviour of **_commitlog_** is to print to the stdout of your 77 | terminal which might not be what you wish to do. 78 | 79 | So, if you wish to ever write to a file , you can use the `--out FILE` flag to 80 | write the output to a file instead. 81 | 82 | ```sh 83 | $ commitlog g -o ./CHANGELOG.md 84 | ``` 85 | 86 | > **Note**: commitlog will overwrite the file with the new output, make sure you 87 | > create a backup of the file when working with this. 88 | 89 | > **Note**: In coming versions an append mode will be added to the CLI to avoid 90 | > having to deal with this manually 91 | 92 |

release

93 | 94 | The `release` sub-command is a complimentary sub-command added to commitlog to 95 | help you with managing release versions. I understand that most languages have 96 | their own package version management and you might want to work with them but 97 | that's also why the `release` sub-command isn't something you need, it's there 98 | for cases where you might wanna use it. 99 | 100 | My primary usecase is when working with repositories that work with multiple 101 | languages and I'd prefer a unified version. 102 | 103 | The `release` command doesn't modify your source code files but instead handles 104 | the version with it's own file named `.commitlog.release`, which just holds the 105 | **version** number right now and while this does have the X.X.X format (semantic 106 | versioning format) the increments or how you handle them doesn't have to be. 107 | 108 | The command is flexible enough for you to combine and create your own way of 109 | versioning. 110 | 111 | ##### Initialize 112 | 113 | ```sh 114 | $ commitlog release --init 115 | # or 116 | $ commitlog r --init 117 | ``` 118 | 119 | Once initialized, you'll see a `.commitlog.release` file in your repo with the 120 | version `v0.0.0` to start with. 121 | 122 | ##### Increments 123 | 124 | Post that you can use the remaining flags to help you incrementing the version 125 | as needed. 126 | 127 | ```sh 128 | $ commitlog r --major # change to v1.0.0 129 | $ commitlog r --minor # change to v0.1.0 130 | $ commitlog r --patch # change to v0.0.1 131 | $ commitlog r --pre # change to v0.0.0-beta.0 132 | $ commitlog r --pre --pre-tag="dev" # change to v0.0.0-dev.0 133 | 134 | # or go bonkers 135 | $ commitlog r --patch --pre --pre-tag="dev" # change to v0.0.1-dev.0 136 | $ commitlog r --major --patch --pre --pre-tag="dev" # change to v1.0.1-dev.0 137 | ``` 138 | 139 | #### Git actions 140 | 141 | Most times you'd also want a tool like this to create commits and tags for you 142 | which is fair, so `release` does come with a few git actions. 143 | 144 | - `--commit` (will create a commit and tag it for you) 145 | - `--push` (will push the commits and tags for you) 146 | 147 | The whole command would look a little something like this 148 | 149 | ```sh 150 | $ commitlog r --patch --commit --push 151 | ``` 152 | 153 |

Advanced

154 | 155 | These are not really hard to guess or achieve but are in the advanced section as 156 | this isn't something a beginner user might need to mess with. If you have other 157 | use cases that you feel like should be added here, raise a issue. 158 | 159 |

Selective Log Ranges

160 | There's enough cases where the entire history between the tags makes no sense. You might just want a specific set of commits and this is very easy to do with commitlog 161 | 162 | ```sh 163 | $ commitlog g --start HEAD --end HEAD~3 164 | # would return the last 3 commits 165 | ``` 166 | 167 | And as you might have understood, commitlog does work with git's revision system 168 | so you can reuse git's own revision pointers as needed. Though it's mostly 169 | easier to just use the HASH since, finding the hashes in `git log` is easier 170 | than finding the number you have to type after the `HEAD~` 171 | 172 |

From a different repo

173 | A lot more often you might need to generate logs for a sub-repo when working with a huge multirepo folder which a lot of sub-modules and switching worktree for the changelog might not be something you wish to do. 174 | 175 | In cases like these the `-p` or `--path` flag can be used with the `generate` 176 | flag 177 | 178 | ```sh 179 | $ commitlog g -p ./sub/module -s HEAD~3 180 | # would return the commits from HEAD~3 to the next tag or end of all commits. 181 | ``` 182 | 183 |

Categorize

184 | You wouldn't be using commitlog otherwise so this obviously has to exist. 185 | 186 | As for why is this turned off by default? I just don't use commit standards and 187 | mostly just need the commits between tags and very rarely need the categories to 188 | help me but doesn't change the fact that someone else might need it. 189 | 190 | So, how does commitlog categorize? using regex's , or more like comma seperated 191 | regex's. 192 | 193 | The implementation approach might bring some issue but I'm going to wait for 194 | them instead of over fixing something that might never really happen. 195 | 196 | Anyway, a simple example for a non-scoped commitlint styled categorization would 197 | look something like this . 198 | 199 | ```sh 200 | $ commitlog g --categories="feat:,fix:" 201 | ``` 202 | 203 | **Output:** 204 | 205 | ```md 206 | ## feat: 207 | 110c9b260e6de1e2be9af28b3592c373ab6fc501 feat: handling for pre increment 208 | 209 | 9080580575d3579b3d11dd114830eb128f0c8130 feat: releaser base maj,min,patch setup 210 | 211 | b513e53cbbc30e5b667fbba373b9589911a47ac0 feat: generator subcommand implementation 212 | 213 | ## fix: 214 | 5bafe9d105298001707c7c816e60d3ef0257a816 fix: tag creation 215 | ``` 216 | 217 | This could be made a little more neater using a better regex like so 218 | 219 | ```sh 220 | $ commitlog g --categories="^feat,^fix" 221 | ``` 222 | 223 | **Output**: 224 | 225 | ```md 226 | ## ^feat 227 | e0ce9c693c554158b7b4841b799524164d9c3e83 feat(releaser): add init and pre-tag handlers 228 | 229 | 110c9b260e6de1e2be9af28b3592c373ab6fc501 feat: handling for pre increment 230 | 231 | 9080580575d3579b3d11dd114830eb128f0c8130 feat: releaser base maj,min,patch setup 232 | 233 | b513e53cbbc30e5b667fbba373b9589911a47ac0 feat: generator subcommand implementation 234 | 235 | ## ^fix 236 | 5bafe9d105298001707c7c816e60d3ef0257a816 fix: tag creation 237 | 238 | 540bb3d7419aab314fdb999dd57eeac3c53f5fad fix doc generation 239 | 240 | 87d40ddbd463ad71b3af8b7edb8ac8176ecbf2f5 fix tests for new param 241 | ``` 242 | 243 | As visible, you find more commits in the 2nd one since the regex matches more 244 | cases and gives you more information. You are free to modify these to make them 245 | work with other patterns that you might follow. 246 | 247 | Also the titles are going to be the regex's you pass. A future version will add 248 | a way for you to add label's to the regex though that's a little harder to 249 | achieve without making the flags very verbose so I've avoided it for now. 250 | 251 | > **Note**: This is the initial implementation of this and might change in a 252 | > future major version since this flag feels a little more frictional than the 253 | > other approaches I have in mind. Feel free to recommend other ways to do this. 254 | 255 |

CLI

256 | 257 | This is the entire CLI reference, which you can also access by using the `-h` 258 | flag on the downloaded binary. 259 | 260 | **`commitlog -h`** 261 | 262 | ``` 263 | NAME: 264 | commitlog - commits to changelogs 265 | 266 | USAGE: 267 | commitlog [global options] command [command options] [arguments...] 268 | 269 | COMMANDS: 270 | generate, g commits to changelogs 271 | release, r manage .commitlog.release version 272 | help, h Shows a list of commands or help for one command 273 | 274 | GLOBAL OPTIONS: 275 | --help, -h show help (default: false) 276 | ``` 277 | 278 | --- 279 | 280 | **`commitlog g -h`** 281 | 282 | ``` 283 | NAME: 284 | commitlog generate - commits to changelogs 285 | 286 | USAGE: 287 | commitlog generate [command options] [arguments...] 288 | 289 | OPTIONS: 290 | --categories value categories to use, includes all commits by default. any text you add here will be used to create categories out of the commits 291 | --end END, -e END END reference for the commit to stop including commits at.This is exclusive of the given commit reference 292 | --out FILE, -o FILE path to the output FILE 293 | --path PATH, -p PATH root with the '.git' folder PATH (default: ".") 294 | --promo add promo text to the end of output (default: false) 295 | --start START, -s START START reference for the commit to include commits from,This is inclusive of the given commit reference 296 | --stdio print to the stdout (default: true) 297 | ``` 298 | 299 | --- 300 | 301 | **`commitlog r -h`** 302 | 303 | ``` 304 | NAME: 305 | commitlog release - manage .commitlog.release version 306 | 307 | USAGE: 308 | commitlog release [command options] [arguments...] 309 | 310 | OPTIONS: 311 | --commit if true will create a commit and tag, of the changed version (default: false) 312 | --init initialise commitlog release (default: false) 313 | --major create a major version (default: false) 314 | --minor create a minor version (default: false) 315 | --patch create a patch version (default: false) 316 | --path PATH, -p PATH PATH to a folder where .commitlog.release exists or is to be created.(note: do not use `--commit` or `--push` if the file isn't in the root) (default: ".") 317 | --pre create a pre-release version. will default to patch increment unlessspecified and not already a pre-release (default: false) 318 | --pre-tag value create a pre-release version (default: "beta") 319 | --push if true will create push the created release commit + tag on origin (default: false) 320 | ``` 321 | -------------------------------------------------------------------------------- /docs/styles.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;600;700&display=swap"); 2 | 3 | :root { 4 | --base: #fff; 5 | --surface: #efefef; 6 | --text: #333; 7 | --muted: #444; 8 | --accent: dodgerblue; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --base: #111; 14 | --surface: #333; 15 | --text: #eee; 16 | --muted: #ddd; 17 | --accent: dodgerblue; 18 | } 19 | } 20 | 21 | html, 22 | body { 23 | background: var(--base); 24 | } 25 | 26 | html { 27 | font-size: 87.5%; 28 | /*14px*/ 29 | } 30 | 31 | body { 32 | max-width: 100ch; 33 | margin: 0 auto; 34 | padding: 1em; 35 | color: var(--text); 36 | font-family: "Fira Code", monospace; 37 | font-weight: 400; 38 | line-height: 1.75; 39 | } 40 | 41 | h1, 42 | h2, 43 | h3, 44 | h4, 45 | h5 { 46 | margin: 3rem 0 1.38rem; 47 | font-family: "Fira Code", monospace; 48 | font-weight: 400; 49 | line-height: 1.3; 50 | } 51 | 52 | h1 { 53 | margin-top: 0; 54 | font-size: 3.052rem; 55 | } 56 | 57 | h2 { 58 | font-size: 2.441rem; 59 | } 60 | 61 | h3 { 62 | font-size: 1.953rem; 63 | } 64 | 65 | h4 { 66 | font-size: 1.563rem; 67 | } 68 | 69 | h5 { 70 | font-size: 1.25rem; 71 | } 72 | 73 | small, 74 | .text_small { 75 | font-size: 0.8rem; 76 | } 77 | 78 | pre, 79 | code { 80 | font-size: 1rem; 81 | } 82 | 83 | code { 84 | padding: 5px; 85 | border: 1px solid var(--surface); 86 | } 87 | 88 | pre { 89 | white-space: pre-wrap; 90 | padding: 10px; 91 | border: 1px solid var(--surface); 92 | } 93 | 94 | pre>code { 95 | padding: 0px; 96 | border: 0px; 97 | } 98 | 99 | a { 100 | color: inherit; 101 | text-underline-offset: 4px; 102 | } 103 | 104 | a:hover { 105 | color: var(--accent); 106 | } 107 | 108 | hr { 109 | border: 0px; 110 | border-top: 1px solid var(--surface); 111 | } 112 | 113 | blockquote { 114 | margin: 0px; 115 | padding: 0px; 116 | border-left: 2px solid var(--muted); 117 | padding-left: 10px; 118 | } 119 | 120 | #search-container { 121 | display: block; 122 | margin:0 auto; 123 | } 124 | 125 | #search-container > input[type="text"] { 126 | width: 100%; 127 | background: var(--base); 128 | color: var(--text); 129 | padding: 0.5rem; 130 | border-radius: 4px; 131 | border: 2px solid var(--surface); 132 | } 133 | 134 | #search-container > input[type="text"]:hover { 135 | border-color: var(--text); 136 | } 137 | 138 | #search-results { 139 | display: flex; 140 | flex-direction: column; 141 | align-items: flex-start; 142 | justify-content: flex-start; 143 | max-height: 200px; 144 | overflow: auto; 145 | } 146 | 147 | .mudkip-search-item { 148 | margin: 0.25rem; 149 | display: block; 150 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/barelyhuman/commitlog/v3 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/go-git/go-git/v5 v5.8.1 7 | github.com/urfave/cli/v2 v2.25.7 8 | golang.org/x/mod v0.12.0 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= 2 | dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 3 | github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 4 | github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= 5 | github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= 6 | github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= 7 | github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= 8 | github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= 9 | github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= 10 | github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= 11 | github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 12 | github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 13 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 14 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 15 | github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= 16 | github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= 17 | github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= 18 | github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 19 | github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 20 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 21 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 22 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 23 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 24 | github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= 25 | github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= 26 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= 27 | github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 28 | github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 29 | github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= 30 | github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= 31 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 32 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 33 | github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= 34 | github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= 35 | github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= 36 | github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= 37 | github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= 38 | github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= 39 | github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= 40 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 41 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 42 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 43 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 44 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 45 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 46 | github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= 47 | github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= 48 | github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 49 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 50 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 51 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 52 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 53 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 54 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 55 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 56 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 57 | github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= 58 | github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= 59 | github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= 60 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 61 | github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= 62 | github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= 63 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 64 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 65 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 66 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 67 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 68 | github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= 69 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 70 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 71 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 72 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 73 | github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= 74 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 75 | github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 76 | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 77 | github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= 78 | github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= 79 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 80 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 81 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 82 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 83 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 84 | github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= 85 | github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 86 | github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 87 | github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= 88 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= 89 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 90 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 91 | golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 92 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 93 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 94 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 95 | golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 96 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 97 | golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= 98 | golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= 99 | golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= 100 | golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= 101 | golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= 102 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 103 | golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= 104 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 105 | golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= 106 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 107 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 108 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 109 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 110 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 111 | golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= 112 | golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= 113 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 114 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 115 | golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 116 | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 117 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 118 | golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= 119 | golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= 120 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 121 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 122 | golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= 123 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 124 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 125 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 126 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 127 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 128 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 129 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 130 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 131 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 132 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 133 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 134 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 135 | golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 136 | golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 137 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 138 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 139 | golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 140 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 141 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 142 | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 143 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 144 | golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= 145 | golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 146 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 147 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 148 | golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 149 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 150 | golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 151 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 152 | golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 153 | golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= 154 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 155 | golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= 156 | golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= 157 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 158 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 159 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 160 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 161 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 162 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 163 | golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 164 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 165 | golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= 166 | golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 167 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 168 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 169 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 170 | golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 171 | golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= 172 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 173 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 174 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 175 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 176 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 177 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 178 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 179 | gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 180 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 181 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 182 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 183 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 184 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 185 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 186 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 187 | -------------------------------------------------------------------------------- /lib/commands.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "log" 5 | "os/exec" 6 | "strings" 7 | ) 8 | 9 | func Command(cmd *exec.Cmd) error { 10 | var w strings.Builder 11 | cmd.Stderr = &w 12 | err := cmd.Run() 13 | if err != nil { 14 | log.Println(strings.TrimSpace(w.String())) 15 | return err 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /lib/commits.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "log" 5 | "strings" 6 | 7 | "github.com/go-git/go-git/v5" 8 | "github.com/go-git/go-git/v5/plumbing" 9 | "github.com/go-git/go-git/v5/plumbing/object" 10 | ) 11 | 12 | func IsHashATag(currentRepository *git.Repository, hash plumbing.Hash) bool { 13 | isTag := false 14 | tags, _ := currentRepository.Tags() 15 | tags.ForEach(func(tagRef *plumbing.Reference) error { 16 | revHash, err := currentRepository.ResolveRevision(plumbing.Revision(tagRef.Name())) 17 | if err != nil { 18 | return err 19 | } 20 | if *revHash == hash { 21 | isTag = true 22 | } 23 | return nil 24 | }) 25 | return isTag 26 | } 27 | 28 | func GetCommitFromString(repo *git.Repository, commitString string) *object.Commit { 29 | if commitString == "" { 30 | return nil 31 | } 32 | 33 | hash, err := repo.ResolveRevision(plumbing.Revision(commitString)) 34 | if err != nil { 35 | log.Fatal("Unable to get Repo head:", err) 36 | } 37 | 38 | commitRef, err := repo.CommitObject(*hash) 39 | if err != nil { 40 | log.Fatal("Unable to get resolve commit:", err) 41 | } 42 | return commitRef 43 | } 44 | 45 | func CommitToLog(c *object.Commit) string { 46 | var commitMsg strings.Builder 47 | commitMsg.WriteString(c.Hash.String()) 48 | commitMsg.WriteString(" ") 49 | commitMsg.WriteString(strings.Split(c.Message, "\n")[0]) 50 | return commitMsg.String() 51 | } 52 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "embed" 5 | "fmt" 6 | "os" 7 | "time" 8 | 9 | "github.com/barelyhuman/commitlog/v3/commands" 10 | "github.com/urfave/cli/v2" 11 | ) 12 | 13 | //go:embed .commitlog.release 14 | var version string 15 | 16 | func main() { 17 | app := &cli.App{ 18 | Name: "commitlog", 19 | Usage: "commits to changelogs", 20 | CommandNotFound: cli.ShowCommandCompletions, 21 | Action: func(c *cli.Context) error { 22 | fmt.Println( 23 | "[commitlog] we no longer support direct invocation, please use the subcommand `generate` to generate a log or `release` to manage your .commitlog.release", 24 | ) 25 | 26 | return nil 27 | }, 28 | Version: version, 29 | Compiled: time.Now(), 30 | HideVersion: false, 31 | Commands: []*cli.Command{ 32 | { 33 | Name: "generate", 34 | Aliases: []string{"g"}, 35 | Usage: "commits to changelogs", 36 | Action: func(c *cli.Context) error { 37 | return commands.Commitlog(c) 38 | }, 39 | Flags: []cli.Flag{ 40 | &cli.StringFlag{ 41 | Name: "path", 42 | Value: ".", 43 | Aliases: []string{"p"}, 44 | Usage: "root with the '.git' folder `PATH`", 45 | }, 46 | &cli.BoolFlag{ 47 | Name: "promo", 48 | Usage: "add promo text to the end of output", 49 | }, 50 | &cli.StringFlag{ 51 | Name: "out", 52 | Aliases: []string{"o"}, 53 | Usage: "path to the output `FILE`", 54 | }, 55 | &cli.BoolFlag{ 56 | Name: "stdio", 57 | Value: true, 58 | Usage: "print to the stdout", 59 | }, 60 | &cli.StringFlag{ 61 | Name: "categories", 62 | Value: "", 63 | Usage: "categories to use, includes all commits by default. any text you add here will be used to create categories out of the commits", 64 | }, 65 | &cli.StringFlag{ 66 | Name: "start", 67 | Aliases: []string{"s"}, 68 | Usage: "`START` reference for the commit to include commits from," + 69 | "This is inclusive of the given commit reference", 70 | }, 71 | &cli.StringFlag{ 72 | Name: "end", 73 | Aliases: []string{"e"}, 74 | Usage: "`END` reference for the commit to stop including commits at." + 75 | "This is exclusive of the given commit reference", 76 | }, 77 | }, 78 | }, 79 | { 80 | Name: "release", 81 | Aliases: []string{"r"}, 82 | Usage: "manage .commitlog.release version", 83 | Action: func(c *cli.Context) error { 84 | return commands.Release(c) 85 | }, 86 | Flags: []cli.Flag{ 87 | &cli.BoolFlag{ 88 | Name: "init", 89 | Value: false, 90 | Usage: "initialise commitlog release", 91 | }, 92 | &cli.StringFlag{ 93 | Name: "path", 94 | Value: ".", 95 | Aliases: []string{"p"}, 96 | Usage: "`PATH` to a folder where .commitlog.release exists or is to be created." + 97 | "(note: do not use `--commit` or `--push` if the file isn't in the root)", 98 | }, 99 | &cli.BoolFlag{ 100 | Name: "pre", 101 | Value: false, 102 | Usage: "create a pre-release version. will default to patch increment unless" + 103 | "specified and not already a pre-release", 104 | }, 105 | &cli.StringFlag{ 106 | Name: "pre-tag", 107 | Value: "beta", 108 | Usage: "create a pre-release version", 109 | }, 110 | &cli.BoolFlag{ 111 | Name: "major", 112 | Value: false, 113 | Usage: "create a major version", 114 | }, 115 | &cli.BoolFlag{ 116 | Name: "minor", 117 | Value: false, 118 | Usage: "create a minor version", 119 | }, 120 | &cli.BoolFlag{ 121 | Name: "patch", 122 | Value: false, 123 | Usage: "create a patch version", 124 | }, 125 | &cli.BoolFlag{ 126 | Name: "commit", 127 | Value: false, 128 | Usage: "if true will create a commit and tag, of the changed version", 129 | }, 130 | &cli.BoolFlag{ 131 | Name: "push", 132 | Value: false, 133 | Usage: "if true will create push the created release commit + tag on origin", 134 | }, 135 | }, 136 | }, 137 | }, 138 | } 139 | 140 | err := app.Run(os.Args) 141 | if err != nil { 142 | fmt.Fprintf(os.Stderr, "[commitlog] %v", err) 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /pkg/generator.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "regexp" 9 | "strings" 10 | 11 | "github.com/barelyhuman/commitlog/v3/lib" 12 | "github.com/go-git/go-git/v5" 13 | "github.com/go-git/go-git/v5/plumbing/object" 14 | ) 15 | 16 | // commitsByCategory is a collection of commits by a given key 17 | // the _key_ can be `all-changes` or a dynamic key / pattern defined 18 | // by the user 19 | type commitsByCategory struct { 20 | key string 21 | commits []string 22 | } 23 | 24 | type Generator struct { 25 | repo *git.Repository 26 | dirPath string 27 | startRef string 28 | endRef string 29 | addPromo bool 30 | categories []string 31 | output struct { 32 | stdio bool 33 | file bool 34 | filePath string 35 | } 36 | classifiedCommits []commitsByCategory 37 | rawCommits []*object.Commit 38 | } 39 | 40 | type GeneratorConfigMod func(*Generator) 41 | 42 | func (g *Generator) openRepo() { 43 | if g.repo != nil { 44 | return 45 | } 46 | 47 | r, err := git.PlainOpen(g.dirPath) 48 | if err != nil { 49 | log.Fatal("Error opening Repository: ", err) 50 | } 51 | g.repo = r 52 | } 53 | 54 | func (g *Generator) readCommitsInTags() (err error) { 55 | // make sure the repo is open 56 | g.openRepo() 57 | 58 | var commits []*object.Commit 59 | 60 | var latestTagCommit *object.Commit 61 | var previousTagCommit *object.Commit 62 | 63 | commitsIter, err := g.repo.Log(&git.LogOptions{}) 64 | if err != nil { 65 | err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) 66 | return 67 | } 68 | defer commitsIter.Close() 69 | 70 | // loop through the commits to get the 71 | // most recent tagged commit and the 2nd most recent 72 | // tagged commit 73 | for { 74 | c, err := commitsIter.Next() 75 | 76 | if err == io.EOF { 77 | break 78 | } 79 | 80 | isTag := lib.IsHashATag(g.repo, c.Hash) 81 | if isTag { 82 | if latestTagCommit == nil { 83 | latestTagCommit = c 84 | } else if previousTagCommit == nil { 85 | previousTagCommit = c 86 | break 87 | } 88 | } 89 | } 90 | 91 | if latestTagCommit == nil && previousTagCommit == nil { 92 | err = fmt.Errorf("failed to get tags, check if you have at least one tag or provide commit references instead") 93 | return 94 | } 95 | 96 | commitsIter, err = g.repo.Log(&git.LogOptions{From: latestTagCommit.Hash}) 97 | 98 | if err != nil { 99 | err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) 100 | return 101 | } 102 | defer commitsIter.Close() 103 | 104 | for { 105 | c, err := commitsIter.Next() 106 | 107 | if err == io.EOF { 108 | break 109 | } 110 | 111 | // do not include the last matching commit 112 | if previousTagCommit != nil && c.Hash == previousTagCommit.Hash { 113 | break 114 | } 115 | 116 | commits = append(commits, c) 117 | } 118 | 119 | // this will either have commits between 2 tags or all commits if no tags exist 120 | g.rawCommits = commits 121 | 122 | return 123 | 124 | } 125 | 126 | func (g *Generator) readCommitsInRange() (err error) { 127 | // make sure the repo is open 128 | g.openRepo() 129 | 130 | var commits []*object.Commit 131 | var commitsIter object.CommitIter 132 | 133 | startHash := lib.GetCommitFromString(g.repo, g.startRef) 134 | endHash := lib.GetCommitFromString(g.repo, g.endRef) 135 | 136 | if startHash != nil { 137 | commitsIter, err = g.repo.Log(&git.LogOptions{From: startHash.Hash}) 138 | } else { 139 | commitsIter, err = g.repo.Log(&git.LogOptions{}) 140 | } 141 | 142 | if err != nil { 143 | err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) 144 | return 145 | } 146 | 147 | for { 148 | c, err := commitsIter.Next() 149 | 150 | if err == io.EOF { 151 | break 152 | } 153 | 154 | if endHash != nil && c.Hash == endHash.Hash { 155 | break 156 | } 157 | 158 | commits = append(commits, c) 159 | } 160 | 161 | g.rawCommits = commits 162 | 163 | return 164 | 165 | } 166 | 167 | // ReadCommmits will try to collect commits in the given range 168 | // or default to current tag to the previous tag or current commit to 169 | // recent tag, in the same order of priority 170 | func (g *Generator) ReadCommmits() (err error) { 171 | // make sure the repo is open 172 | g.openRepo() 173 | 174 | if len(g.startRef) > 0 || len(g.endRef) > 0 { 175 | err = g.readCommitsInRange() 176 | if err != nil { 177 | return 178 | } 179 | } else { 180 | err = g.readCommitsInTags() 181 | if err != nil { 182 | return 183 | } 184 | } 185 | 186 | return 187 | } 188 | 189 | func (g *Generator) Classify() (err error) { 190 | // write the classification using the existing commits 191 | if len(g.categories) == 0 { 192 | allCommits := []string{} 193 | 194 | for _, commit := range g.rawCommits { 195 | allCommits = append(allCommits, lib.CommitToLog(commit)) 196 | } 197 | 198 | g.classifiedCommits = []commitsByCategory{ 199 | { 200 | key: "All Changes", 201 | commits: allCommits, 202 | }, 203 | } 204 | 205 | return 206 | } 207 | 208 | for _, catg := range g.categories { 209 | rgx, err := regexp.Compile(catg) 210 | if err != nil { 211 | break 212 | } 213 | 214 | catgCommits := []string{} 215 | 216 | for _, commit := range g.rawCommits { 217 | if !rgx.Match([]byte(commit.Message)) { 218 | continue 219 | } 220 | 221 | catgCommits = append(catgCommits, lib.CommitToLog(commit)) 222 | } 223 | 224 | g.classifiedCommits = append(g.classifiedCommits, commitsByCategory{ 225 | key: catg, 226 | commits: catgCommits, 227 | }) 228 | } 229 | 230 | return 231 | 232 | } 233 | 234 | func (g *Generator) Generate() (err error) { 235 | 236 | var inMardown strings.Builder 237 | 238 | for _, class := range g.classifiedCommits { 239 | 240 | // title 241 | inMardown.Write([]byte("##")) 242 | inMardown.Write([]byte(" ")) 243 | inMardown.Write([]byte(class.key)) 244 | 245 | inMardown.Write([]byte("\n")) 246 | 247 | // each commit with 2 returns to separate the long description one's 248 | for _, commitMsg := range class.commits { 249 | inMardown.Write([]byte(commitMsg)) 250 | inMardown.Write([]byte("\n\n")) 251 | } 252 | 253 | } 254 | 255 | if g.output.stdio { 256 | fmt.Println(inMardown.String()) 257 | } 258 | 259 | if g.output.file { 260 | err = os.WriteFile(g.output.filePath, []byte(inMardown.String()), os.ModePerm) 261 | if err != nil { 262 | return 263 | } 264 | } 265 | 266 | return 267 | } 268 | 269 | func CreateGenerator(path string, mods ...GeneratorConfigMod) *Generator { 270 | generator := &Generator{ 271 | dirPath: path, 272 | } 273 | 274 | for _, mod := range mods { 275 | mod(generator) 276 | } 277 | 278 | return generator 279 | } 280 | 281 | func WithPromo() GeneratorConfigMod { 282 | return func(g *Generator) { 283 | g.addPromo = true 284 | } 285 | } 286 | 287 | func WithOutputToFile(filePath string) GeneratorConfigMod { 288 | return func(g *Generator) { 289 | g.output.file = true 290 | g.output.filePath = filePath 291 | } 292 | } 293 | 294 | func WithOutputToStdio() GeneratorConfigMod { 295 | return func(g *Generator) { 296 | g.output.stdio = true 297 | } 298 | } 299 | 300 | func WithStartReference(startRef string) GeneratorConfigMod { 301 | return func(g *Generator) { 302 | g.startRef = startRef 303 | } 304 | } 305 | 306 | func WithEndReference(endRef string) GeneratorConfigMod { 307 | return func(g *Generator) { 308 | g.endRef = endRef 309 | } 310 | } 311 | 312 | func WithCategories(categories string) GeneratorConfigMod { 313 | return func(g *Generator) { 314 | parts := strings.Split(categories, ",") 315 | g.categories = parts 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /pkg/releaser.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | 8 | "golang.org/x/mod/semver" 9 | ) 10 | 11 | type version struct { 12 | major int 13 | minor int 14 | patch int 15 | preString string 16 | } 17 | 18 | type Releaser struct { 19 | raw string 20 | v version 21 | next version 22 | preTag string 23 | } 24 | 25 | func (r *Releaser) HasPrerelease() bool { 26 | return len(r.v.preString) > 0 27 | } 28 | 29 | func (r *Releaser) String() (s string) { 30 | var b strings.Builder 31 | 32 | b.Write([]byte("v")) 33 | 34 | b.WriteString(strconv.Itoa(r.next.major)) 35 | b.WriteString(".") 36 | b.WriteString(strconv.Itoa(r.next.minor)) 37 | b.WriteString(".") 38 | b.WriteString(strconv.Itoa(r.next.patch)) 39 | 40 | if len(r.next.preString) > 0 { 41 | b.Write([]byte("-")) 42 | b.Write([]byte(r.next.preString)) 43 | } 44 | 45 | s = b.String() 46 | 47 | return 48 | } 49 | 50 | type ReleaserMod func(*Releaser) 51 | 52 | func CreateNewReleaser(vString string, mods ...ReleaserMod) (r *Releaser, err error) { 53 | 54 | if !semver.IsValid(vString) { 55 | err = fmt.Errorf("invalid version string") 56 | return 57 | } 58 | 59 | r = &Releaser{} 60 | r.raw = vString 61 | 62 | simplifiedV := semver.Canonical(vString) 63 | 64 | vParts := strings.Split(simplifiedV, ".") 65 | 66 | preParts := strings.Split(vParts[2], "-") 67 | 68 | if len(preParts) > 1 { 69 | r.v.patch, err = strconv.Atoi(preParts[0]) 70 | } else { 71 | r.v.patch, err = strconv.Atoi(vParts[2]) 72 | } 73 | 74 | if err != nil { 75 | return 76 | } 77 | 78 | r.v.minor, err = strconv.Atoi(vParts[1]) 79 | if err != nil { 80 | return 81 | } 82 | 83 | majorStr := strings.Replace(vParts[0], "v", "", -1) 84 | r.v.major, err = strconv.Atoi(majorStr) 85 | if err != nil { 86 | return 87 | } 88 | 89 | r.v.preString = semver.Prerelease(vString) 90 | 91 | r.preTag = strings.Split(r.v.preString, ".")[0] 92 | 93 | r.next.major = r.v.major 94 | r.next.minor = r.v.minor 95 | r.next.patch = r.v.patch 96 | r.next.preString = r.v.preString 97 | 98 | for _, mod := range mods { 99 | mod(r) 100 | } 101 | 102 | return 103 | } 104 | 105 | func WithPrerelease(pre string) ReleaserMod { 106 | return func(r *Releaser) { 107 | r.next.preString = pre 108 | } 109 | } 110 | 111 | func WithPrereleaseIncrement() ReleaserMod { 112 | return func(r *Releaser) { 113 | 114 | // if a pre string already exists 115 | if r.HasPrerelease() { 116 | preParts := strings.Split(r.v.preString, ".") 117 | prePointer, _ := strconv.Atoi(preParts[1]) 118 | prePointer += 1 119 | preParts[1] = strconv.Itoa(prePointer) 120 | preParts[0] = r.preTag 121 | r.next.preString = strings.Join(preParts[:], ".") 122 | return 123 | } 124 | 125 | preToCreate := []string{ 126 | r.preTag, 127 | "0", 128 | } 129 | 130 | r.next.preString = strings.Join(preToCreate[:], ".") 131 | } 132 | } 133 | 134 | func WithMajorIncrement() ReleaserMod { 135 | return func(r *Releaser) { 136 | r.next.major += 1 137 | } 138 | } 139 | 140 | func WithMinorIncrement() ReleaserMod { 141 | return func(r *Releaser) { 142 | r.next.minor += 1 143 | } 144 | } 145 | 146 | func WithPatchIncrement() ReleaserMod { 147 | return func(r *Releaser) { 148 | r.next.patch += 1 149 | } 150 | } 151 | 152 | func WithMajorReset() ReleaserMod { 153 | return func(r *Releaser) { 154 | r.next.major = 0 155 | } 156 | } 157 | 158 | func WithMinorReset() ReleaserMod { 159 | return func(r *Releaser) { 160 | r.next.minor = 0 161 | } 162 | } 163 | 164 | func WithPatchReset() ReleaserMod { 165 | return func(r *Releaser) { 166 | r.next.patch = 0 167 | } 168 | } 169 | 170 | func WithPrereleaseReset() ReleaserMod { 171 | return func(r *Releaser) { 172 | preParts := strings.Split(r.v.preString, ".") 173 | // reset something like `beta.1` to `beta.0` 174 | preParts[1] = strconv.Itoa(0) 175 | nextPreString := strings.Join(preParts[:], ".") 176 | nextPreString = strings.TrimPrefix(nextPreString, "-") 177 | r.next.preString = nextPreString 178 | } 179 | } 180 | 181 | func WithClearPrerelease() ReleaserMod { 182 | return func(r *Releaser) { 183 | r.next.preString = "" 184 | } 185 | } 186 | 187 | func WithPreTag(preTag string) ReleaserMod { 188 | return func(r *Releaser) { 189 | r.preTag = preTag 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /scripts/cross-compile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euxo pipefail 4 | 5 | rm -rf ./bin 6 | 7 | build_commands=(' 8 | apk add make curl git \ 9 | ; GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o bin/linux-arm64/alvu \ 10 | ; GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/linux-amd64/alvu \ 11 | ; GOOS=linux GOARCH=arm go build -ldflags="-s -w" -o bin/linux-arm/alvu \ 12 | ; GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o bin/windows-386/alvu \ 13 | ; GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o bin/windows-amd64/alvu \ 14 | ; GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o bin/darwin-amd64/alvu \ 15 | ; GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o bin/darwin-arm64/alvu 16 | ') 17 | 18 | # run a docker container with osxcross and cross compile everything 19 | docker run -it --rm -v $(pwd):/usr/local/src -w /usr/local/src \ 20 | golang:alpine3.16 \ 21 | sh -c "$build_commands" 22 | 23 | # create archives 24 | cd bin 25 | for dir in $(ls -d *); 26 | do 27 | cp ../README.md $dir 28 | cp ../LICENSE $dir 29 | mkdir -p $dir/docs 30 | cp -r ../docs/* $dir/docs 31 | 32 | # remove the download document and styles 33 | rm -rf $dir/docs/download.md 34 | rm -rf $dir/docs/styles.css 35 | 36 | tar cfzv "$dir".tgz $dir 37 | rm -rf $dir 38 | done 39 | cd .. -------------------------------------------------------------------------------- /scripts/generate-docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | curl -o mudkip.tgz -L https://github.com/barelyhuman/mudkip/releases/latest/download/linux-amd64.tgz 4 | tar -xvzf mudkip.tgz 5 | install linux-amd64/mudkip /usr/local/bin 6 | 7 | mudkip --baseurl='/commitlog/' --stylesheet="./docs/styles.css" 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/get-release-urls.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/env bash 3 | 4 | curl -sL https://api.github.com/repos/barelyhuman/commitlog/releases | jq '[ .[0].assets[] | {name:.name,url:.url} ]' > api_urls.json 5 | 6 | cat >./docs/download.md< 8 | 9 | commitlog | downloads 10 | 11 | 12 | 13 | 14 | ### [commitlog](/) 15 | 16 | [Home](/) [Manual](/manual) [Download](/download) [API](/api) 17 | 18 | #### Downloads 19 | 20 | EOF 21 | 22 | jq -c '.[]' api_urls.json | while read i; do 23 | url=$(echo $i | jq '.url' --raw-output) 24 | name=$(echo $i | jq '.name' --raw-output) 25 | bdurl=$(curl -sL $url | jq -r '.browser_download_url') 26 | echo "[$name]($bdurl) " >> ./docs/download.md 27 | done --------------------------------------------------------------------------------