Giter Club home page Giter Club logo

go-gitignore's Introduction

go-gitignore

Package go-gitignore provides an interface for parsing .gitignore files, either individually, or within a repository, and matching paths against the retrieved patterns. Path matching is done using fnmatch as specified by git, with support for recursive matching via the ** pattern.

import "github.com/denormal/go-gitignore"

// match a file against a particular .gitignore
ignore, err := gitignore.NewFromFile("/my/.gitignore")
if err != nil {
    panic(err)
}
match := ignore.Match("/my/file/to.check")
if match != nil {
    if match.Ignore() {
        return true
    }
}

// or match against a repository
//  - here we match a directory path relative to the repository
ignore, err := gitignore.NewRepository( "/my/git/repository" )
if err != nil {
    panic(err)
}
match := ignore.Relative("src/examples", true)
if match != nil {
    if match.Include() {
        fmt.Printf(
            "include src/examples/ because of pattern %q at %s",
			match, match.Position(),
		)
    }
}

// if it's not important whether a path matches, but whether it is
// ignored or included...
if ignore.Ignore("src/test") {
    fmt.Println("ignore src/test")
} else if ignore.Include("src/github.com") {
    fmt.Println("include src/github.com")
}

For more information see godoc github.com/denormal/go-gitignore.

Patterns

go-gitignore supports the same .gitignore pattern format and matching rules as defined by git:

  • A blank line matches no files, so it can serve as a separator for readability.

  • A line starting with # serves as a comment. Put a backslash \ in front of the first hash for patterns that begin with a hash.

  • Trailing spaces are ignored unless they are quoted with backslash \.

  • An optional prefix ! which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined. Put a backslash \ in front of the first ! for patterns that begin with a literal !, for example, \!important!.txt.

  • If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find a match with a directory. In other words, foo/ will match a directory foo and paths underneath it, but will not match a regular file or a symbolic link foo (this is consistent with the way how pathspec works in general in Git).

  • If the pattern does not contain a slash /, Git treats it as a shell glob pattern and checks for a match against the pathname relative to the location of the .gitignore file (relative to the toplevel of the work tree if not from a .gitignore file).

  • Otherwise, Git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not match a / in the pathname. For example, Documentation/*.html matches Documentation/git.html but not Documentation/ppc/ppc.html or tools/perf/Documentation/perf.html.

  • A leading slash matches the beginning of the pathname. For example, /*.c matches cat-file.c but not mozilla-sha1/sha1.c.

Two consecutive asterisks ** in patterns matched against full pathname may have special meaning:

  • A leading ** followed by a slash means match in all directories. For example, **/foo matches file or directory foo anywhere, the same as pattern foo. **/foo/bar matches file or directory bar anywhere that is directly under directory foo.

  • A trailing /** matches everything inside. For example, abc/** matches all files inside directory abc, relative to the location of the .gitignore file, with infinite depth.

  • A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, a/**/b matches a/b, a/x/b, a/x/y/b and so on.

  • Other consecutive asterisks are considered invalid.

Installation

go-gitignore can be installed using the standard Go approach:

go get github.com/denormal/go-gitignore

License

Copyright (c) 2016 Denormal Limited

MIT License

go-gitignore's People

Contributors

denormal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

go-gitignore's Issues

bar/** seems to work differently than .gitignore

For files like


.
├ foo
│  └ bar
│     └ some_file.txt
└ bar
   └ other_file.txt

When I ignore:

bar/**

Both foo/bar/some_file.txt and bar/other_file.txt will be ignored.

But for .gitignore, only bar/other_file.txt will be ignored.

Parser panics on line containing just whitespace

Hi, just ran into a bug where lines that only contain whitespace cause a panic in the parser. This is quite a tricky one to diagnose because such lines are very hard to spot.

Reproduction:

package main

import "github.com/denormal/go-gitignore"

func main() {
	// or match against a repository
	//  - here we match a directory path relative to the repository
	matcher, err := gitignore.NewRepository( "/tmp/panic" )
	if err != nil {
		panic(err)
	}

	matcher.Relative("panic_test", false)
}

Panics if the file /tmp/panic/.gitignore contains a line with a single space e.g.

# Next line contains just whitespace
 

The relative path resolution fails when the repository path is '/'

go-gitignore/gitignore.go

Lines 250 to 252 in ae8ad1d

// extract the relative path of this file
_prefix := len(i._base) + 1
_rel := string(path[_prefix:])

When the Match logic tries to resolve a relative path from 2 paths (eg. basepath, fullpath), it simply tries to obtain the path after the length of the basepath in fullpath, i.e.

	_prefix := len(i._base) + 1
	_rel := string(path[_prefix:])

However, this would fail when the your basepath was /. Also, there is already a function which finds out the relative path, i.e. path.filepath.Rel, why not simply use that?

_rel, err := filepath.Rel(i._base, path)

Note: The / being the repository path is a case when I am trying to find out all the files in the file-system which satisfy a certain gitignore.

Support for parsing CODEOWNERS files

Given the similarity in parsing rules for gitignore files & CODEOWNERS files, it would be great if this library added support for parsing CODEOWNERS files as well. I am unable to find a Go implementation for parsing CODEOWNERS that follows the spec correctly, as does yours.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.