├── .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 | [](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
--------------------------------------------------------------------------------