-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Rakefile
224 lines (175 loc) · 4.97 KB
/
Rakefile
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# -*- ruby -*-
require "open-uri"
require "yaml"
require "rubygems"
require "json"
ENV["P4CONFIG"] = ".p4config"
ENV["P4CHARSET"] = "utf8" # let's hope this works... :/
TRACE = !!Rake.application.options.trace
RakeFileUtils.verbose_flag = TRACE
DEVNULL = TRACE ? "" : "> /dev/null"
FAST = ENV['FAST']
NOOP = ENV["NOOP"]
COLLABORATORS = %w(zenspider)
GITHUB_USER = `git config github.user`.chomp
GITHUB_ORGS = %w[seattlerb minitest]
GITHUB_TOKEN = `git config github.oauth-token`.chomp
GIT_P4 = File.expand_path "vendor/git-p4"
ALL_PROJECTS = IO.read("projects.txt").
split("\n").
reject { |p| p =~ /^#/ }.
sort_by { |p| p.downcase }
def git_p4 *args
sh "#{GIT_P4} #{args.join ' '} #{DEVNULL}" unless NOOP
end
def github url_suffix, options = {}
url = "https://api.github.com/#{url_suffix}"
flags = [ "-H \"Authorization: token #{GITHUB_TOKEN}\"",
"-isS",
'-H "Content-Type: application/json"',
'-H "Accept: application/json"',
'-X POST'].join " "
data = JSON.dump options
cmd = "curl #{flags} -d '#{data}' #{url} #{DEVNULL}"
sh cmd unless NOOP
end
def link_hash link
return {} unless link
Hash[link.scan(/<([^>]+)>; rel="([^"]+)"/).map(&:reverse)]
end
def paged_json_array url
result = []
begin
warn "url: #{url}" if TRACE
req = URI.parse(url).open :http_basic_authentication => [GITHUB_USER,
GITHUB_TOKEN]
link = link_hash req.meta["link"]
url = link["next"]
result.concat JSON.load(req.read)
end while url
result
end
def git *args
sh "git #{args.join ' '} #{DEVNULL}" unless NOOP
end
def projects
return ALL_PROJECTS unless ENV["PROJECTS"]
ENV["PROJECTS"].split ","
end
desc "Pull projects from Perforce."
task :default => :pull
desc "Pull projects from Perforce and push to GitHub."
task :sync => %w(pull push)
def git_dirty
if `git diff`.lines.size != 0 and not ENV["DIRTY"] then
warn "git is dirty. skipping"
true
end
end
task :pull do
next if git_dirty
projects.each do |name|
warn "* Pulling #{name} from Perforce." if TRACE
src = "//src/#{name}/dev@all"
name.downcase!
dest = "projects/#{name}"
unless File.directory? dest
mkdir_p dest
Dir.chdir dest do
git_p4 :clone, src, "."
git "remote add origin [email protected]:#{GITHUB_ORGS.first}/#{name}.git"
end
else
Dir.chdir dest do
git "pull -q --rebase origin master"
git_p4 :rebase
# TODO? git p4 submit
end
end
end
end
task :gc do
projects.each do |name|
name.downcase!
dest = "projects/#{name}"
if File.directory? dest then
Dir.chdir dest do
git "gc -q"
end
else
warn "#{dest} does not exist!"
end
end
end
def project_names org
paged_json_array("https://api.github.com/orgs/#{org}/repos?per_page=100")
.map { |r| r["name"] }
end
task :push do
next if git_dirty
warn "Getting repos..." if TRACE
repos = GITHUB_ORGS.flat_map { |org| project_names org }
p repos.sort if TRACE
projects.each do |name, project|
name.downcase!
unless repos.include? name
warn " - Creating a new repo!" if TRACE
github "orgs/#{GITHUB_ORGS.first}/repos", :name => name
end
Dir.chdir("projects/#{name}") do
should_push = !repos.include?(name) ||
!system("git diff --quiet origin/master")
should_push_tags = changelog_to_tags || ENV["FORCE_TAGS"]
if should_push then
warn "Pushing #{name} to GitHub." if TRACE
sleep rand(30) unless FAST
git "push origin master"
end
if should_push_tags then
warn "Pushing tags #{name} to GitHub." if TRACE
git "push --tags origin master"
end
end
end
end
desc "wtf"
task :wtf do
base = "~/Work/p4/zss/src/seattlerb_dashboard/dev/lib"
$: << File.expand_path(base)
require "seattlerb_projects"
File.open("projects.txt", "w") do |f|
f.puts SeattlerbProjects.new.projects.flatten.sort.join("\n")
end
end
def changelog_to_tags
cmd = %w[git log
--abbrev-commit
--pretty=tformat:"~~~%n%h: %s"
-p
--
History.rdoc
History.md
History.txt
].join " "
output = `#{cmd}`.encode(Encoding::UTF_8, invalid: :replace)
changes = output.split(/~~~\n/).drop 1
seen = `git tag`.lines.map(&:chomp).map { |k| [k, true] }.to_h
versions = changes.map { |change|
lines = change.lines
sha, ver = lines[0], lines.grep(/^\+=+ \d/).first
next unless sha =~ /prep|Branching .+? to version/i
next unless ver
sha = sha[/^\w+/]
ver, date = ver.split.values_at(1, 3)
next unless date =~ /^\d\d\d\d-\d\d-\d\d$/
next unless ver =~ /^\d+\.\d+\.\d+/
[date, "v#{ver}", sha]
}.compact
additions = versions.sort.map { |date, ver, sha|
next if seen[ver]
cmd = "git tag %-12s %s # %s" % [ver, sha, date]
warn cmd
system cmd
}.compact
! additions.empty?
end