abak-flow 0.3.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|