Introducing ingoreinit - A CLI tool for creating gitignores
Tags: go, tooling, cli, productivity
Published: 2022-10-23 16:26:00

Let's talk generating .gitignore files - a file every git repo should have. Some tools for scaffolding projects like `create-tauri-app` or `composer create-project` initialize .gitignore for you. But what about applications which do not use these? Like when generating new solution in Visual Studio or creating a new Go app. Many developers tend to manually copy the ignore files from their previous projects or go to [github/gitignore](https://github.com/github/gitignore) to get them. In my opinion, this is very tedious and can be achieved in a simpler and faster way - via the CLI.

This is where [**ignoreinit**](https://github.com/Loupeznik/ignoreinit) comes in. 

## The tool

I originally wanted to create a tool like this mainly for the aformentioned reasons - it is faster and more comfortable to get your .gitignore from the command line. And as somebody who is always working on new projects, I wanted to simplify my workflow as much as possible.

The tool itself is written in Go, leveraging a library called [`go-github`](https://github.com/google/go-github) to fetch gitignores. In the first iteration, it can either download a new gitignore file based on selected language and framework (for now it has to be one of the gitignore files present in the aformentioned `github/gitignore` repo) or replace existing gitignore by specifying new language and path of the ignore to be replaced.

The flow is as follows:
- *ignoreinit* parses the CLI parameters
- It fetches the list of all available gitignores from the repo
- Determines whether a .gitignore is available for selected language or framework
- If it is, *ignoreinit* downloads the ignore file and creates .gitignore with its contents in the selected directory

The flow is pretty simple. As is the main function which handles the fetching itself, I will include a snippet at the end of the article.

### How to get and use ignoreinit

If you find the tool interesting, it can currently be installed in three ways. If you have Go already installed on your machine, you could just do `go install github.com/loupeznik/ignoreinit@latest`, this should automatically install it and add it to your `$PATH` (if you have path to Go binaries in your `$PATH` already). Cloning the repo and building the binary yourself is also a possibility. 

If you are Go-less, you can always get it from the [Releases](https://github.com/Loupeznik/ignoreinit/releases) page of the [Github repo](https://github.com/Loupeznik/ignoreinit). Binaries for Linux, Windows and MacOS are available. Using the last method, you might want to add the binary to your `$PATH` (e.g. moving it for example to `/usr/local/bin` on Linux or appending the folder which the executable resides in to your `PATH` on Windows).

Usage is pretty straightforward:

```bash
ignoreinit <init|replace> <language> <location>
```

For example:

```powershell
# Initialize a new .gitignore for Go in current directory
ignoreinit init go
# Initialize a new .gitignore for Python in different directory
ignoreinit init python C:\Dev\my-flask-api
# Replace gitignore in current directory
ignoreinit replace c++
```

## Conclusion and future development

This article briefly introduced the [**ignoreinit**](https://github.com/Loupeznik/ignoreinit) CLI tool for generating .gitignore files conveniently from the commandline. In the future, I would like to enhance the tool to also support .dockerignore files, have more .gitignore repositories available and have the tool available in package managers like snap, apt or chocolatey for smoother installation experience.

If you've made it this far, thanks for reading. Until next time...

P.S. the aformentioned snippet:

```go
func getIgnore(language string, location string, isNew bool) error {
	client := github.NewClient(nil)
	ctx := context.Background()
	options := &github.RepositoryContentGetOptions{}

	_, directoryContent, _, err := client.Repositories.GetContents(ctx, gitOwner, gitRepo, "/", options)

	if err != nil {
		return err
	}

	var url string

	for _, file := range directoryContent {
		if !strings.EqualFold(strings.Split(*file.Name, ".")[0], language) {
			continue
		}

		url = file.GetPath()

		break
	}

	if url == "" {
		return fmt.Errorf("could not find .gitignore for %s", language)
	}

	reader, _, err := client.Repositories.DownloadContents(ctx, gitOwner, gitRepo, url, options)

	if err != nil {
		return err
	}

	defer reader.Close()

	bytes, err := io.ReadAll(reader)

	if err != nil {
		return err
	}

	var file *os.File
	fullPath := path.Join(location, ".gitignore")

	if isNew {
		file, err = os.Create(fullPath)
	} else {
		file, err = os.OpenFile(fullPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
	}

	if err != nil {
		return err
	}

	defer file.Close()

	_, err = file.Write(bytes)

	if err != nil {
		return err
	}

	return nil
}
``` 

Cover image credit to [Gabriel Heinzer](https://unsplash.com/@6heinz3r?utm_source=unsplash&utm_medium=referral) on [Unsplash](https://unsplash.com/s/photos/gitignore?utm_source=unsplash&utm_medium=referral).

This article was originally posted over at [blog.dzarsky.eu](https://blog.dzarsky.eu/introducing-ingoreinit-a-cli-tool-for-creating-gitignores).