-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathbatch.go
More file actions
152 lines (132 loc) · 4.24 KB
/
batch.go
File metadata and controls
152 lines (132 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
Copyright 2015 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package batch is the source for a command-line tool to pull all of the data
// from a Github repository and write it into a local clone of that repository.
//
// You need to clone the repository yourself (including the "refs/pull/*" refs)
// before running the tool.
//
// Example Usage:
// git clone https://github.com/google/git-appraise git-appraise/
// cd git-appraise
// git fetch origin '+refs/pull/*:refs/pull/*'
// ~/bin/github-mirror --target google/git-appraise --local ./ -auth-token <YOUR_AUTH_TOKEN>
//
// Note that the "-auth-token" flag is optional, but highly recommended. Without it
// your API requests will be throttled to 60 per hour.
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"github.com/google/git-appraise/repository"
"github.com/google/go-github/github"
"github.com/google/git-pull-request-mirror/auth"
"github.com/google/git-pull-request-mirror/mirror"
)
var remoteRepository = flag.String("target", "", "Github repository to read data from")
var localRepositoryDir = flag.String("local", ".", "Local repository to write notes to")
var token = flag.String("auth-token", "", "Github OAuth token with either the `repo' or `public_repo' scopes: https://github.com/settings/tokens")
var quiet = flag.Bool("quiet", false, "Don't log information to stdout")
func usage(errorMessage string) {
fmt.Fprintln(os.Stderr, errorMessage)
flag.Usage()
os.Exit(1)
}
func main() {
flag.Parse()
splitTarget := strings.Split(*remoteRepository, "/")
if len(splitTarget) != 2 {
usage("Target repository is required, in the format `user/repo'")
}
userName := splitTarget[0]
repoName := splitTarget[1]
localDirInfo, err := os.Stat(*localRepositoryDir)
if err != nil {
log.Fatal(err)
}
if !localDirInfo.IsDir() {
usage("Local repository must be a directory")
}
local, err := repository.NewGitRepo(*localRepositoryDir)
if err != nil {
log.Fatal("Couldn't open local repository: ", err.Error(), "\n",
"Make sure you clone the remote repository locally first!")
}
tokenAuth := *token != ""
if !tokenAuth {
fmt.Fprintln(os.Stderr, "Not using authentication. Note that this will be EXTREMELY SLOW;")
fmt.Fprintln(os.Stderr, "you get 60 requests to the github API per hour.")
fmt.Fprint(os.Stderr, auth.TokenHelp)
}
var client *github.Client
if tokenAuth {
client = auth.TokenClient(*token)
} else {
client = auth.UnauthenticatedClient()
}
_, _, err = client.Repositories.Get(context.TODO(), userName, repoName)
if err != nil {
log.Fatal("Error fetching repository info: ", err.Error())
}
errOutput := make(chan error, 1000)
nErrors := 0
go func() {
for err := range errOutput {
if !*quiet {
log.Println(err)
}
nErrors++
}
}()
statuses, err := mirror.GetAllStatuses(userName, repoName, client, errOutput)
if err != nil {
log.Fatal("Error reading statuses: ", err.Error())
}
reviews, err := mirror.GetAllPullRequests(local, userName, repoName, client, errOutput)
if err != nil {
log.Fatal("Error reading pull requests: ", err.Error())
}
close(errOutput)
nStatuses := len(statuses)
nReviews := len(reviews)
var l *log.Logger
if *quiet {
l = log.New(ioutil.Discard, "", 0)
} else {
l = log.New(os.Stdout, "", 0)
}
logChan := make(chan string, 1000)
go func() {
for msg := range logChan {
l.Println(msg)
}
}()
l.Printf("Done reading! Read %d statuses, %d PRs", nStatuses, nReviews)
l.Printf("Committing...\n")
if err := mirror.WriteNewReports(statuses, local, logChan); err != nil {
log.Fatal(err)
}
if err := mirror.WriteNewReviews(reviews, local, logChan); err != nil {
log.Fatal(err)
}
close(logChan)
l.Printf("Done! Hit %d errors", nErrors)
if nErrors > 0 {
os.Exit(1)
}
}