-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch to a pure Go implementation of Git
- Loading branch information
Showing
6 changed files
with
403 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,95 @@ | ||
package extractor | ||
|
||
import ( | ||
"bufio" | ||
"log" | ||
"os/exec" | ||
"strings" | ||
|
||
"errors" | ||
"github.com/dunglas/calavera/schema" | ||
gogit "gopkg.in/src-d/go-git.v4" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
var gitPath string | ||
// Git extracts metadata from the Git repository containing Markdown files. | ||
type Git struct { | ||
inputDirectory string | ||
gitDirectory string | ||
repository *gogit.Repository | ||
} | ||
|
||
func init() { | ||
var err error | ||
func findGitDir(path string) (string, error) { | ||
if _, err := os.Stat(path + "/.git/config"); err == nil { | ||
return path + "/.git", nil | ||
} | ||
|
||
gitPath, err = exec.LookPath("git") | ||
if nil != err { | ||
log.Fatalln("git is not available in the PATH. Install it to extract git metadata.") | ||
parentDir := filepath.Dir(path) | ||
if strings.HasSuffix(parentDir, "/") { | ||
return "", errors.New("No Git repository found") | ||
} | ||
|
||
return findGitDir(parentDir) | ||
} | ||
|
||
// Git extracts metadata from the Git repository containing Markdown files. | ||
type Git struct { | ||
// NewGit returns a new instance properly configured of the Git extractor | ||
func NewGit(inputDirectory string) (*Git, error) { | ||
var err error | ||
var gitDirectory string | ||
|
||
if gitDirectory, err = findGitDir(inputDirectory); nil != err { | ||
return nil, err | ||
} | ||
|
||
if r, err := gogit.NewFilesystemRepository(gitDirectory); nil == err { | ||
return &Git{ | ||
inputDirectory: inputDirectory, | ||
gitDirectory: gitDirectory, | ||
repository: r, | ||
}, nil | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
// Extract extracts the list of contributors to the file, and date of modifications. | ||
func (git Git) Extract(creativeWork *schema.CreativeWork, path string) error { | ||
if "" == gitPath { | ||
return nil | ||
} | ||
path, _ = filepath.Rel(filepath.Dir(git.gitDirectory), git.inputDirectory+"/"+path) | ||
|
||
cmd := exec.Command(gitPath, "log", "--format=%an;%ae;%aI", path) | ||
stdout, err := cmd.StdoutPipe() | ||
ref, err := git.repository.Head() | ||
if nil != err { | ||
return err | ||
} | ||
|
||
if err := cmd.Start(); err != nil { | ||
c, err := git.repository.Commit(ref.Hash()) | ||
if nil != err { | ||
return err | ||
} | ||
|
||
scanner := bufio.NewScanner(stdout) | ||
for scanner.Scan() { | ||
parts := strings.Split(strings.TrimSpace(scanner.Text()), ";") | ||
revs, err := gogit.References(c, path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
author := schema.NewPerson(parts[0], parts[1]) | ||
creativeWork.Author = append([]schema.Person{*author}, creativeWork.Author...) | ||
for _, v := range revs { | ||
if !authorExists(creativeWork.Author, v.Author.Email) { | ||
author := schema.NewPerson(v.Author.Name, v.Author.Email) | ||
creativeWork.Author = append([]schema.Person{*author}, creativeWork.Author...) | ||
} | ||
|
||
creativeWork.DateCreated = parts[2] | ||
if "" == creativeWork.DateModified { | ||
creativeWork.DateModified = parts[2] | ||
creativeWork.DateModified = &v.Author.When | ||
if nil == creativeWork.DateCreated { | ||
creativeWork.DateCreated = &v.Author.When | ||
} | ||
} | ||
|
||
if err := scanner.Err(); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
if err := cmd.Wait(); err != nil { | ||
log.Fatalln("You are not in a git repository.") | ||
return err | ||
// authorExists tests if an author is already in the list | ||
func authorExists(authors []schema.Person, email string) bool { | ||
for _, p := range authors { | ||
if email == p.Email { | ||
return true | ||
} | ||
} | ||
|
||
return nil | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.