Skip to content

MoonMoon1919/gignore

Repository files navigation

GIGNORE

A Go library for programmatically managing .gitignore and .dockignore files with intelligent conflict detection and automatic resolution.

Features

  • πŸ” Intelligent conflict detection - Finds redundant, unreachable, and ineffective rules
  • πŸ”§ Automatic conflict resolution - Smart reordering and cleanup of ignore files
  • πŸ“ Repository abstraction - Works with files, memory, or custom storage backends
  • βœ… Comprehensive validation - Prevents invalid patterns and configurations
  • 🎯 Type-safe rule creation - File, directory, extension, and glob patterns

Installation

go get github.com/MoonMoon1919/gignore

Quick Start

package main

import (
    "fmt"
    "github.com/MoonMoon1919/gignore"
)

func main() {
    // Create a new ignore file service
    repo := gignore.NewFileRepository(gignore.RenderOptions{})
    service := gignore.NewService(repo)

    // Add rules to .gitignore
    service.AddExtensionRule(".gitignore", "log", gignore.INCLUDE)
    service.AddDirectoryRule(".gitignore", "build", gignore.RECURSIVE, gignore.INCLUDE)
    service.AddFileRule(".gitignore", "config.json", gignore.INCLUDE)

    // Create exceptions
    service.AddFileRule(".gitignore", "build/important.txt", gignore.EXCLUDE)

    // Automatically fix any conflicts
    fixes, err := service.AutoFix(".gitignore", 10)
    if err != nil {
        panic(err)
    }

    for _, fix := range fixes {
        fmt.Println("Applied:", fix)
    }
}

Core Concepts

Rule Types

File Rules - Exact file paths

service.AddFileRule(path, "src/main.go", gignore.INCLUDE)
// Generates: src/main.go

Extension Rules - File extensions

service.AddExtensionRule(path, "log", gignore.INCLUDE)
// Generates: *.log

Directory Rules - Directory patterns with different modes

// Just the directory
service.AddDirectoryRule(path, "build", gignore.DIRECTORY, gignore.INCLUDE)
// Generates: build/

// Everything in directory recursively
service.AddDirectoryRule(path, "build", gignore.RECURSIVE, gignore.INCLUDE)
// Generates: build/**

// Direct children only
service.AddDirectoryRule(path, "build", gignore.CHILDREN, gignore.INCLUDE)
// Generates: build/*

// Directory anywhere in tree
service.AddDirectoryRule(path, "temp", gignore.ANYWHERE, gignore.INCLUDE)
// Generates: **/temp

// Root-level only (leading slash)
service.AddDirectoryRule(path, "node_modules", gignore.ROOT_ONLY, gignore.INCLUDE)
// Generates: /node_modules

Glob Rules - Complex patterns

service.AddGlobRule(path, "temp*.log", gignore.INCLUDE)
// Generates: temp*.log

Actions

  • gignore.INCLUDE - Ignore this pattern (no ! prefix)
  • gignore.EXCLUDE - Don't ignore this pattern (! prefix for exceptions)

Conflict Detection

The library automatically detects four types of conflicts:

Semantic Conflicts - Same pattern with opposite actions

config.json
!config.json  # ← Conflicting actions

Redundant Rules - Duplicate patterns

*.log
*.log  # ← Redundant

Unreachable Rules - Broader patterns make specific ones meaningless

build/**
build/  # ← Unreachable (build/** already covers this)

Ineffective Rules - Exception rules with no prior exclusion

!build/important.txt  # ← Ineffective (nothing to override)
build/**

Advanced Usage

Manual Conflict Analysis

// Load existing .gitignore
var ignoreFile gignore.IgnoreFile
err := repo.Load(".gitignore", &ignoreFile)

// Find conflicts
conflicts := ignoreFile.FindConflicts()
for _, conflict := range conflicts {
    fmt.Printf("Conflict: %s between '%s' and '%s'\n",
        conflict.ConflictType,
        conflict.Left.Render(),
        conflict.Right.Render())
}

Rule Reordering

// Move a rule before or after another rule
result, err := service.MoveRule(".gitignore", "!important.txt", "build/**", gignore.AFTER)

Parsing Existing Files

// Parse .gitignore content
content := `*.log
build/
!build/important.txt`

var ignoreFile gignore.IgnoreFile
err := gignore.Parse(content, &ignoreFile)

Error Handling

The library uses explicit error types for better error handling:

err := service.AddFileRule(".gitignore", "config.json", gignore.INCLUDE)
if err != nil {
    switch {
    case errors.Is(err, gignore.SemanticConflictError):
        // Handle semantic conflict
    case errors.Is(err, gignore.RedundantRuleError):
        // Handle redundant rule
    case errors.Is(err, gignore.UnreachableRuleError):
        // Handle unreachable rule
    }
}

Testing

The library includes comprehensive test coverage. The repository interface is simple to fake.

// Create fake repository for testing
type FakeRepository struct {
	files map[string]string
}

func (f *FakeRepository) Load(path string, ignoreFile *IgnoreFile) error {
	content, ok := f.files[path]
	if !ok {
		return fileReadError
	}

	return LoadFile(strings.NewReader(content), ignoreFile)
}

func (f *FakeRepository) Save(path string, ignoreFile *IgnoreFile) error {
	content := Render(ignoreFile, RenderOptions{})
	f.files[path] = content

	return nil
}

func NewFakeRepository() FakeRepository {
	return FakeRepository{
		files: make(map[string]string),
	}
}

service := gignore.NewService(repo)

// Test your ignore file logic

Contributing

See CONTRIBUTING

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

If you encounter any issues or have questions, please open an issue on GitHub.

About

Go package for managing ignore files

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors