abak-flow 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -1
- data/README.md +13 -30
- data/Rakefile +25 -0
- data/VERSION +1 -1
- data/abak-flow.gemspec +23 -19
- data/bin/request +1 -2
- data/lib/abak-flow/branch.rb +108 -0
- data/lib/abak-flow/branches.rb +68 -0
- data/lib/abak-flow/configuration.rb +67 -0
- data/lib/abak-flow/locales/en.yml +32 -0
- data/lib/abak-flow/locales/ru.yml +32 -0
- data/lib/abak-flow/manager.rb +35 -0
- data/lib/abak-flow/messages.rb +86 -0
- data/lib/abak-flow/pull_request.rb +39 -199
- data/lib/abak-flow/repository.rb +71 -0
- data/lib/abak-flow/request.rb +88 -198
- data/lib/abak-flow/version.rb +1 -1
- data/lib/abak-flow/visitor.rb +43 -0
- data/lib/abak-flow.rb +20 -13
- data/spec/abak-flow/branch_spec.rb +55 -0
- data/spec/abak-flow/branches_spec.rb +20 -0
- data/spec/abak-flow/configuration_spec.rb +73 -0
- data/spec/abak-flow/git_spec.rb +12 -0
- data/spec/abak-flow/github_client_spec.rb +15 -0
- data/spec/abak-flow/messages_spec.rb +146 -0
- data/spec/abak-flow/project_spec.rb +52 -0
- data/spec/abak-flow/pull_request_spec.rb +353 -0
- data/spec/abak-flow/system_spec.rb +97 -0
- data/spec/spec_helper.rb +17 -0
- metadata +82 -31
- data/lib/abak-flow/config.rb +0 -20
- data/lib/abak-flow/extensions.rb +0 -125
- data/lib/abak-flow/github_client.rb +0 -13
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGU3ZjFmYjE3OWMyMDM4NTI1NWJjYzQxZDFjZTM5YmQ2YmQ0M2Q1ZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NjViMDJhOWE1ZmRhMTU0ZjZkNjVkNjhlYTBiZmE0ZTM1NjgyYzlkZA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NWE0M2ZjYmJkMDQ0MWU4OWUxZDBiODk4NTU0N2Q2M2IyZTU4ZGIyZTgxZTBl
|
10
|
+
NGEyY2M4YTZjMjI4ZmZjY2FlZjJjMTZiMzg0YThmYTBkN2E1ODA2NzVjYjc2
|
11
|
+
MjFiZDlkZDdiMmU1ODExNzJiNzBhYzA0MDE1ZWNjMTIxMjViOWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzZkYmQ0OThkMDcxYjFlNmI4MTdlYmRjOTY1NzBmNDYxNTI3Mjc5M2M5ZjVh
|
14
|
+
YmM2ZDJlM2ZhOTk0YjQ5MWJkZmVkNmVkY2I2MmMwOTYxMTQyOWZhOTBiMGEw
|
15
|
+
YzVmYjYzNjY4ZDZiOGZmYjEyMzFkOTM4MGFhYjI1YjgwZTQ1ZGU=
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,9 @@ Abak-flow
|
|
2
2
|
=========
|
3
3
|
Нет, это не новая идеология ведения проекта, это всего лишь набор утилит которые помогают связать использование [git-flow](https://github.com/nvie/gitflow) и [github flow](http://scottchacon.com/2011/08/31/github-flow.html)
|
4
4
|
|
5
|
-
**Начиная с версии v0.2.1 используется авторизация OAuth2. [Как ей
|
5
|
+
**Начиная с версии v0.2.1 используется авторизация OAuth2. [Как ей пользоваться?](https://github.com/Strech/abak-flow/wiki/How-start-work-with-new-abak-flow)**
|
6
|
+
|
7
|
+
**Начиная с версии v1.0.0 используется новый формат конфигурации. [Как мигрировать старую?](https://github.com/Strech/abak-flow/wiki/How-start-work-with-abak-flow-v1.0.0)**
|
6
8
|
|
7
9
|
# Концепция
|
8
10
|
Идеология git-flow использует следующий набор веток:
|
@@ -25,10 +27,10 @@ Github-flow же наоборот ведет основную разработк
|
|
25
27
|
|
26
28
|
# Установка
|
27
29
|
|
28
|
-
$ gem install abak-flow
|
30
|
+
$ gem install abak-flow -v 1.0.0
|
29
31
|
$ git config --global alias.request '!request'
|
30
|
-
$ git config --global abak.
|
31
|
-
$ git config --global abak.
|
32
|
+
$ git config --global abak-flow.oauth-user YOUR_GITHUB_MAIL@gmail.com
|
33
|
+
$ git config --global abak-flow.oauth-token 0123456789YOUR_GITHUB_API_TOKEN
|
32
34
|
$ git remote add upstream git://github.com/GITHUB_PROJECT_USER/GITHUB_PROJECT_NAME.git
|
33
35
|
|
34
36
|
### А если я использую прокси, как быть?
|
@@ -40,13 +42,13 @@ Github-flow же наоборот ведет основную разработк
|
|
40
42
|
|
41
43
|
---
|
42
44
|
|
43
|
-
**Заметьте:** В конфиге git, значением *abak.
|
45
|
+
**Заметьте:** В конфиге git, значением *abak.oauth-user* должен являться тот email адрес, под которым вы заходите на github
|
44
46
|
|
45
47
|
**Обратите внимание:** В данном контексте под **upstream** подразумевается адрес репозитория в который будут оформляться pull request. А репозиторием **origin** будет являться ваш форк
|
46
48
|
|
47
49
|
# С чего начать?
|
48
50
|
|
49
|
-
$ git request
|
51
|
+
$ git request checkup
|
50
52
|
|
51
53
|
или
|
52
54
|
|
@@ -58,7 +60,7 @@ Github-flow же наоборот ведет основную разработк
|
|
58
60
|
### Самый простой способ начать новую задачу:
|
59
61
|
|
60
62
|
$ git checkout develop
|
61
|
-
$ git
|
63
|
+
$ git flow feature start 'TASK-001'
|
62
64
|
$ touch 'hello.txt' && echo 'Hello world!' > hello.txt
|
63
65
|
$ git commit -a -m 'Hello world commit'
|
64
66
|
$ git request publish
|
@@ -68,7 +70,7 @@ Github-flow же наоборот ведет основную разработк
|
|
68
70
|
Теперь то же самое, только словами:
|
69
71
|
|
70
72
|
* Переключимся в ветку develop
|
71
|
-
*
|
73
|
+
* git-flow создаст ветку, пригодную для оформления pull request (правила именования и правила самого реквеста)
|
72
74
|
* Простое создание нового файла
|
73
75
|
* Git процедуры добавления своих изменений в репозиторий
|
74
76
|
* Затем публикация вашей ветки на вашем форке (если таковая уже есть, то просто обновление), затем оформление pull request из этой ветки в соответствующую правилам ветку на upstream (в данном случае это будет ветка develop)
|
@@ -76,36 +78,17 @@ Github-flow же наоборот ведет основную разработк
|
|
76
78
|
Для задач, которые должны быть выполнены в виде hotfix принцип тот же:
|
77
79
|
|
78
80
|
$ git checkout master
|
79
|
-
$ git
|
81
|
+
$ git flow hotfix start 'TASK-001'
|
80
82
|
$ …
|
81
83
|
$ git request publish
|
82
84
|
|
83
85
|
*На самом деле переключаться на master или develop в самом начале вовсе не обязательно, этот шаг был приведен для пущей ясности*
|
84
86
|
|
85
|
-
### Обновление ветки на удаленном репозитории:
|
86
|
-
|
87
|
-
$ git checkout feature/TASK-001
|
88
|
-
$ git request update
|
89
|
-
|
90
|
-
### Завершение текущей задачи:
|
91
|
-
Вообще, завершать задачу лучше только после того, как ваш pull request был принят. Почему? На самом деле по ряду причин. По умолчанию эта команда удаляет как вашу текущую ветку с задачей в локальном репозитории и в добавок ко всему - на вашем удаленном репозитории (форке)
|
92
|
-
|
93
|
-
$ git checkout feature/TASK-001
|
94
|
-
$ git request done
|
95
|
-
|
96
|
-
Чтобы оставить какую либо ветку в живых возможно напрямую указать, какую копию ветки **удалить**, локальную или же удаленную (на origin)
|
97
|
-
|
98
|
-
$ git checkout feature/TASK-001
|
99
|
-
$ git request done --origin
|
100
|
-
|
101
|
-
Или же так
|
102
|
-
|
103
|
-
$ git checkout feature/TASK-001
|
104
|
-
$ git request done --local
|
105
|
-
|
106
87
|
## Маленькие хитрости
|
107
88
|
Если сразу правильно именовать ветки, т.е ветку с задачей создавать с именем, такого формата TASK-001, то, в описание pull request автоматически вставится ссылка на задачу в jira, а в имя pull request сразу вставится название, состоящее из имени задачи, т.е TASK-001
|
108
89
|
|
90
|
+
Если делать реквест из ветки не соответствующей формату TASK-001, то в название подставится последний commit message. Если вы считаете, что нужно указать, что-то другое - всегда можно воспользоваться опцией `--title`
|
91
|
+
|
109
92
|
## А помощь?
|
110
93
|
Многие команды имеют какие-то дополнительные опции. Но они нужны только в экзотических случаях. Но при любом раскладе подсказку и тонкий намек всегда можно получить воспользовавших такой командой:
|
111
94
|
|
data/Rakefile
CHANGED
@@ -1 +1,26 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require "yard"
|
4
|
+
require "yard-tomdoc"
|
5
|
+
require "cane/rake_task"
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
|
8
|
+
desc "Ready check"
|
9
|
+
task default: [:quality, :coverage, :doc]
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new(:coverage) do |rspec|
|
12
|
+
ENV["COVERAGE"] = "true"
|
13
|
+
end
|
14
|
+
|
15
|
+
Cane::RakeTask.new(:quality) do |cane|
|
16
|
+
cane.abc_max = 15
|
17
|
+
cane.abc_glob = cane.style_glob = cane.doc_glob = "{lib}/abak-flow/*.rb"
|
18
|
+
cane.style_exclude = %w({lib}/abak-flow/request.rb)
|
19
|
+
cane.style_measure = 120
|
20
|
+
cane.parallel = false
|
21
|
+
end
|
22
|
+
|
23
|
+
YARD::Rake::YardocTask.new(:doc) do |yard|
|
24
|
+
yard.files = %w({apps,models,lib}/**/*.rb)
|
25
|
+
yard.options = %w(--embed-mixins --protected --plugin tomdoc)
|
26
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0
|
1
|
+
1.0
|
data/abak-flow.gemspec
CHANGED
@@ -1,24 +1,28 @@
|
|
1
|
-
#
|
2
|
-
$:.push File.expand_path(
|
3
|
-
require 'abak-flow/version'
|
1
|
+
# coding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
3
|
|
5
|
-
|
6
|
-
s.name = 'abak-flow'
|
7
|
-
s.version = Abak::Flow::VERSION
|
8
|
-
s.authors = ['Strech (aka Sergey Fedorov)']
|
9
|
-
s.email = ['oni.strech@gmail.com']
|
10
|
-
s.homepage = 'https://github.com/Strech/abak-flow'
|
11
|
-
s.summary = %q{Совмещение 2-х подходов разработки Git-flow & Github-flow}
|
12
|
-
s.description = %q{Простой набор правил и комманд, заточеных для работы в git-flow с использование в качестве удаленного репозитория github}
|
4
|
+
require "abak-flow/version"
|
13
5
|
|
14
|
-
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "abak-flow"
|
8
|
+
gem.version = Abak::Flow::VERSION
|
9
|
+
gem.authors = ["Strech (aka Sergey Fedorov)"]
|
10
|
+
gem.email = ["oni.strech@gmail.com"]
|
11
|
+
gem.homepage = "https://github.com/Strech/abak-flow"
|
12
|
+
gem.summary = "Совмещение 2-х подходов разработки Git-flow & Github-flow"
|
13
|
+
gem.description = "Простой набор правил и комманд, заточеных для работы в git-flow с использование в качестве удаленного репозитория github"
|
15
14
|
|
16
|
-
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ['lib']
|
15
|
+
gem.rubyforge_project = "abak-flow"
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
gem.files = `git ls-files`.split("\n")
|
18
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
|
22
|
+
gem.add_runtime_dependency "octokit", "~> 1.19.0"
|
23
|
+
gem.add_runtime_dependency "git", "~> 1.2.5"
|
24
|
+
gem.add_runtime_dependency "commander", ">= 4.1.3"
|
25
|
+
gem.add_runtime_dependency "ruler", ">= 1.4.2"
|
26
|
+
gem.add_runtime_dependency "i18n", ">= 0.6.1"
|
27
|
+
gem.add_runtime_dependency "ansi", ">= 1.4.3"
|
24
28
|
end
|
data/bin/request
CHANGED
@@ -0,0 +1,108 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Abak::Flow
|
4
|
+
class Branch
|
5
|
+
FOLDER_HOTFIX = "hotfix".freeze
|
6
|
+
FOLDER_FEATURE = "feature".freeze
|
7
|
+
TASK_FORMAT = /^\w+\-\d{1,}$/.freeze
|
8
|
+
|
9
|
+
DEVELOPMENT = "develop".freeze
|
10
|
+
MASTER = "master".freeze
|
11
|
+
|
12
|
+
MAPPING = {
|
13
|
+
FOLDER_HOTFIX => MASTER,
|
14
|
+
FOLDER_FEATURE => DEVELOPMENT
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def initialize(branch, manager)
|
18
|
+
@manager = manager
|
19
|
+
@branch = branch.is_a?(Git::Branch) ? branch
|
20
|
+
: manager.git.branch(branch)
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
@branch.full
|
25
|
+
end
|
26
|
+
|
27
|
+
def message
|
28
|
+
@branch.gcommit.message
|
29
|
+
end
|
30
|
+
|
31
|
+
def folder
|
32
|
+
split_prefix_and_task.first
|
33
|
+
end
|
34
|
+
|
35
|
+
def task
|
36
|
+
split_prefix_and_task.last
|
37
|
+
end
|
38
|
+
|
39
|
+
def compare_link(branch)
|
40
|
+
diff = "#{@manager.repository.upstream.owner}:#{branch}...#{@branch}"
|
41
|
+
|
42
|
+
File.join [
|
43
|
+
@manager.github.web_endpoint,
|
44
|
+
@manager.repository.origin.to_s,
|
45
|
+
"compare", diff
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
def update
|
50
|
+
origin = @manager.repository.origin.repo
|
51
|
+
@manager.git.push(origin, @branch)
|
52
|
+
end
|
53
|
+
|
54
|
+
def pick_up_base_name
|
55
|
+
mappable? ? MAPPING[folder]
|
56
|
+
: name
|
57
|
+
end
|
58
|
+
|
59
|
+
def pick_up_title
|
60
|
+
tracker_task? ? task
|
61
|
+
: message
|
62
|
+
end
|
63
|
+
|
64
|
+
# TODO : Вынести в i18n
|
65
|
+
def pick_up_body
|
66
|
+
tracker_task? ? "http://jira.railsc.ru/browse/#{task}"
|
67
|
+
: nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def hotfix?
|
71
|
+
folder == FOLDER_HOTFIX
|
72
|
+
end
|
73
|
+
|
74
|
+
def feature?
|
75
|
+
folder == FOLDER_FEATURE
|
76
|
+
end
|
77
|
+
|
78
|
+
def tracker_task?
|
79
|
+
!(task =~ TASK_FORMAT).nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def mappable?
|
83
|
+
hotfix? || feature?
|
84
|
+
end
|
85
|
+
|
86
|
+
def current?
|
87
|
+
@branch.current
|
88
|
+
end
|
89
|
+
|
90
|
+
def valid?
|
91
|
+
!@branch.name.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_s
|
95
|
+
@branch.to_s
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
def split_prefix_and_task
|
100
|
+
return @folder_and_task if defined? @folder_and_task
|
101
|
+
|
102
|
+
matches = name.match(/^(?<prefix>.+)\/(?<task>.+)$/)
|
103
|
+
|
104
|
+
@folder_and_task = matches.nil? ? [nil, nil]
|
105
|
+
: [matches[:prefix], matches[:task]]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
#
|
3
|
+
# Wrapper class for git branches.
|
4
|
+
# Provides access to git branches and also defines current_branch
|
5
|
+
module Abak::Flow
|
6
|
+
module Branches
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegator "Abak::Flow::Git.instance", :git
|
10
|
+
|
11
|
+
def self.current_branch
|
12
|
+
Branch.new git.branches[git.current_branch]
|
13
|
+
end
|
14
|
+
|
15
|
+
# ==========================================================================
|
16
|
+
# TODO : Refactor
|
17
|
+
# 3. Statistics & Cleaning
|
18
|
+
#
|
19
|
+
# => PullRequest.garbage
|
20
|
+
# => PullRequest.clean
|
21
|
+
# => PullRequest.clean(hard: true)
|
22
|
+
def self.garbage
|
23
|
+
Project.init
|
24
|
+
[Project.upstream.repo, Project.origin.repo].map(&:fetch)
|
25
|
+
|
26
|
+
branches = GithubClient.connection.branches(Project.origin.to_s)
|
27
|
+
.reject { |branch| %w(master develop).include? branch.name }
|
28
|
+
|
29
|
+
messages = Messages.new "pull_request.garbage"
|
30
|
+
messages << [:collected_branches, {count: branches.count}]
|
31
|
+
|
32
|
+
branches.each_with_index do |branch, index|
|
33
|
+
|
34
|
+
# WRONG PREFIX
|
35
|
+
upstream_branch = Git.command_lines("branch", ["-r", "--contain", branch.commit.sha])
|
36
|
+
.select { |branches| branches.include? "upstream/#{branch.prefix}" }
|
37
|
+
|
38
|
+
local_sha = git.branches[branch.name] ? git.branches[branch.name].gcommit.sha : ""
|
39
|
+
|
40
|
+
statuses = {
|
41
|
+
branch_unused: upstream_branch.empty?,
|
42
|
+
branch_differ: !local_sha.empty? && local_sha != branch.commit.sha,
|
43
|
+
branch_missing: local_sha.empty?
|
44
|
+
}
|
45
|
+
|
46
|
+
unless statuses.values.inject &:|
|
47
|
+
messages << [:deletion_allowed, {index: index, branch_name: branch.name}]
|
48
|
+
next
|
49
|
+
end
|
50
|
+
|
51
|
+
diagnoses = statuses.select { |_, bool| bool }.
|
52
|
+
map { |name, _| messages.t name }.
|
53
|
+
map { |msg| " ↪ #{msg}" }.
|
54
|
+
join("\n")
|
55
|
+
|
56
|
+
if statuses.select { |_, bool| bool }.keys == [:missing]
|
57
|
+
messages << [:deletion_possibly, {index: index, branch_name: branch.name, diagnoses: diagnoses}]
|
58
|
+
else
|
59
|
+
messages << [:deletion_restricted, {index: index, branch_name: branch.name, diagnoses: diagnoses}]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
messages
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "i18n"
|
3
|
+
require "ruler"
|
4
|
+
|
5
|
+
module Abak::Flow
|
6
|
+
class Configuration
|
7
|
+
include Ruler
|
8
|
+
|
9
|
+
OPTIONS = [:oauth_user, :oauth_token, :locale, :http_proxy].freeze
|
10
|
+
LOCALE_FILES = File.join(File.dirname(__FILE__), "locales/*.{rb,yml}").freeze
|
11
|
+
|
12
|
+
attr_reader :errors
|
13
|
+
|
14
|
+
def initialize(manager)
|
15
|
+
@manager = manager
|
16
|
+
@errors = []
|
17
|
+
|
18
|
+
configure!
|
19
|
+
end
|
20
|
+
|
21
|
+
def ready?
|
22
|
+
@errors = []
|
23
|
+
|
24
|
+
multi_ruleset do
|
25
|
+
fact(:oauth_user_not_setup) { oauth_user.nil? }
|
26
|
+
fact(:oauth_token_not_setup) { oauth_token.nil? }
|
27
|
+
|
28
|
+
rule([:oauth_user_not_setup]) { @errors << I18n.t("configuration.errors.oauth_user_not_setup") }
|
29
|
+
rule([:oauth_token_not_setup]) { @errors << I18n.t("configuration.errors.oauth_token_not_setup") }
|
30
|
+
end
|
31
|
+
|
32
|
+
@errors.empty? ? true : false
|
33
|
+
end
|
34
|
+
|
35
|
+
def display_name
|
36
|
+
I18n.t("configuration.name")
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def configure!
|
41
|
+
load_gitconfig
|
42
|
+
setup_locale
|
43
|
+
end
|
44
|
+
|
45
|
+
def setup_locale
|
46
|
+
I18n.load_path += Dir.glob(LOCALE_FILES)
|
47
|
+
I18n.locale = locale
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_gitconfig
|
51
|
+
git_config = @manager.git.config.select { |k, _| k.include? "abak-flow." }
|
52
|
+
.map { |k,v| [to_method_name(k), v] }
|
53
|
+
|
54
|
+
config = Hash[git_config]
|
55
|
+
config[:locale] ||= "en"
|
56
|
+
config[:http_proxy] ||= ENV["http_proxy"] || ENV["HTTP_PROXY"]
|
57
|
+
|
58
|
+
OPTIONS.each do |name|
|
59
|
+
define_singleton_method(name) { config[name] }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_method_name(name)
|
64
|
+
name.sub(/abak-flow./, "").gsub(/\W/, "_").to_sym
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
en:
|
2
|
+
configuration:
|
3
|
+
name: Configuration
|
4
|
+
errors:
|
5
|
+
oauth_user_not_setup: Options oauth_user not setted
|
6
|
+
oauth_token_not_setup: Options oauth_token not setted
|
7
|
+
recommendations: "Check [abak-flow] section in ~/.gitcofig file"
|
8
|
+
|
9
|
+
repository:
|
10
|
+
name: Repository
|
11
|
+
errors:
|
12
|
+
origin_not_setup: Repository with name 'origin' not found
|
13
|
+
upstream_not_setup: Repository with name 'upstream' not found
|
14
|
+
recommendations: "Check .git/cofig file"
|
15
|
+
|
16
|
+
pull_request:
|
17
|
+
name: Pull Request
|
18
|
+
|
19
|
+
commands:
|
20
|
+
checkup:
|
21
|
+
fail: You are not prepared!
|
22
|
+
success: "Congratulations, you are ready to ROCK :)"
|
23
|
+
compare:
|
24
|
+
fail: Something goes wrong!
|
25
|
+
updating: "Updating %{branch} → %{upstream}"
|
26
|
+
diverging: "Branches may diverging\nAdvice: switch to branch '%{branch}' and retry operation"
|
27
|
+
publish:
|
28
|
+
fail: Something goes wrong!
|
29
|
+
success: "Pull request successfuly created %{link}"
|
30
|
+
requesting: "Creating pull request %{branch} → %{upstream}"
|
31
|
+
updating: "Updating %{branch} → %{upstream}"
|
32
|
+
nothing: I have nothing to say ...
|
@@ -0,0 +1,32 @@
|
|
1
|
+
ru:
|
2
|
+
configuration:
|
3
|
+
name: Корфигурация
|
4
|
+
errors:
|
5
|
+
oauth_user_not_setup: Не установлена опция oauth_user
|
6
|
+
oauth_token_not_setup: Не установлена опция oauth_token
|
7
|
+
recommendations: "Проверьте секцию [abak-flow] в файле ~/.gitcofig"
|
8
|
+
|
9
|
+
repository:
|
10
|
+
name: Репозиторий
|
11
|
+
errors:
|
12
|
+
origin_not_setup: Репозиторий с именем 'origin' не найден
|
13
|
+
upstream_not_setup: Репозиторий с именем 'upstream' не найден
|
14
|
+
recommendations: Проверьте файл .git/cofig
|
15
|
+
|
16
|
+
pull_request:
|
17
|
+
name: Пулл реквест
|
18
|
+
|
19
|
+
commands:
|
20
|
+
checkup:
|
21
|
+
fail: "Вы не готовы!"
|
22
|
+
success: "Поздравляем, вы готовы чтобы жечь :)"
|
23
|
+
compare:
|
24
|
+
fail: Что-то пошло не так!
|
25
|
+
updating: "Обновление %{branch} → %{upstream}"
|
26
|
+
diverging: "Ветки могут расходиться.\nСовет: переключитесь в ветку '%{branch}' и повторите операцию"
|
27
|
+
publish:
|
28
|
+
fail: Что-то пошло не так!
|
29
|
+
success: "Пулл реквест успешно создан %{link}"
|
30
|
+
requesting: "Создание пулл реквеста %{branch} → %{upstream}"
|
31
|
+
updating: "Обновление %{branch} → %{upstream}"
|
32
|
+
nothing: Мне нечего добавить ...
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "git"
|
3
|
+
require "octokit"
|
4
|
+
|
5
|
+
module Abak::Flow
|
6
|
+
class Manager
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
# preload dependencies
|
10
|
+
configuration
|
11
|
+
repository
|
12
|
+
|
13
|
+
yield self if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def configuration
|
17
|
+
@configuration ||= Configuration.new(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def repository
|
21
|
+
@repository ||= Repository.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def github
|
25
|
+
@github ||= Octokit::Client.new(login: configuration.oauth_user,
|
26
|
+
oauth_token: configuration.oauth_token,
|
27
|
+
proxy: configuration.http_proxy)
|
28
|
+
end
|
29
|
+
|
30
|
+
def git
|
31
|
+
@git ||= Git.open(".")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
require "i18n"
|
3
|
+
|
4
|
+
# TODO : Нужен простой метод, для перевода без скоупа
|
5
|
+
module Abak::Flow
|
6
|
+
class Messages
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_reader :scope, :elements
|
10
|
+
|
11
|
+
def initialize(scope)
|
12
|
+
Configuration.instance
|
13
|
+
|
14
|
+
@scope = scope
|
15
|
+
@elements = []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Iterate elements from locale scope (translating online)
|
19
|
+
#
|
20
|
+
# Returns nothing
|
21
|
+
def each
|
22
|
+
raise ArgumentError, "No block given" unless block_given?
|
23
|
+
|
24
|
+
elements.each do |key|
|
25
|
+
yield translate(key)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Put item to elements
|
30
|
+
#
|
31
|
+
# Returns Symbol
|
32
|
+
def push(element)
|
33
|
+
@elements << element
|
34
|
+
end
|
35
|
+
alias :<< :push
|
36
|
+
|
37
|
+
# section header from locale scope
|
38
|
+
#
|
39
|
+
# Returns String
|
40
|
+
def header
|
41
|
+
translate :header
|
42
|
+
end
|
43
|
+
|
44
|
+
# Print all elements from locale scope without header
|
45
|
+
#
|
46
|
+
# Returns Symbol
|
47
|
+
def to_s
|
48
|
+
return "" if elements.empty?
|
49
|
+
|
50
|
+
elements.collect { |element| translate *element } * "\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
def print
|
54
|
+
return "" if elements.empty?
|
55
|
+
|
56
|
+
all_elements = []
|
57
|
+
elements.each_with_index do |element, index|
|
58
|
+
all_elements << "#{index + 1}. #{translate(*element)}"
|
59
|
+
end
|
60
|
+
|
61
|
+
all_elements * "\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Print section header from locale scope and all elements from scope
|
65
|
+
#
|
66
|
+
# Returns String
|
67
|
+
def pretty_print
|
68
|
+
return "" if elements.empty?
|
69
|
+
|
70
|
+
[header, print] * "\n\n"
|
71
|
+
end
|
72
|
+
alias :pp :pretty_print
|
73
|
+
|
74
|
+
def translate(key, options = {})
|
75
|
+
I18n.t key, {scope: scope}.merge!(options)
|
76
|
+
end
|
77
|
+
alias :t :translate
|
78
|
+
|
79
|
+
def purge!
|
80
|
+
@elements = []
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def_delegator :elements, :empty?
|
85
|
+
end
|
86
|
+
end
|