geometrialab-abak-flow 0.2.3
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.
- data/.gitignore +6 -0
- data/Gemfile +7 -0
- data/README.md +116 -0
- data/Rakefile +1 -0
- data/VERSION +1 -0
- data/bin/request +4 -0
- data/geometrialab-abak-flow.gemspec +24 -0
- data/lib/abak-flow/hub_extensions.rb +111 -0
- data/lib/abak-flow/request.rb +285 -0
- data/lib/abak-flow/version.rb +5 -0
- data/lib/abak-flow.rb +11 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
Abak-flow
|
2
|
+
=========
|
3
|
+
Нет, это не новая идеология ведения проекта, это всего лишь набор утилит которые помогают связать использование [git-flow](https://github.com/nvie/gitflow) и [github flow](http://scottchacon.com/2011/08/31/github-flow.html)
|
4
|
+
|
5
|
+
# Концепция
|
6
|
+
Идеология git-flow использует следующий набор веток:
|
7
|
+
|
8
|
+
* *master* - всегда пригодна для развертывания
|
9
|
+
* *develop* - основная ветка разработки
|
10
|
+
* *hotfix* - ветка для изменений которые попадут на продакшен сервер
|
11
|
+
* *feature* - ветки для крупных задач
|
12
|
+
|
13
|
+
Github-flow же наоборот ведет основную разработку в ветке master, но при этом master является пригодным для развертывания в любой момент.
|
14
|
+
|
15
|
+
После долгих раздумий было принято применить следующий набор правил, для разработки на github:
|
16
|
+
|
17
|
+
1. Вся разработка любой задачи и функционала ведется только в ветках **feature**
|
18
|
+
2. Разработаный функционал из ветки **feature** оформляется pull request только в ветку **develop**
|
19
|
+
3. Все исправления ошибок, которые должны попасть на продакшен сервер делаются только в ветках **hotfix**
|
20
|
+
4. Исправленные ошибки из ветки **hotfix** фофрмляются pull request только в ветку **master**
|
21
|
+
5. После получения исправлений на текущий момент в репозитории инициируется merge ветки **master** в **develop**
|
22
|
+
|
23
|
+
|
24
|
+
# Установка
|
25
|
+
|
26
|
+
$ gem install abak-flow
|
27
|
+
$ git config --global alias.request '!request'
|
28
|
+
$ git config --global abak.apiuser your_github_mail@gmail.com
|
29
|
+
$ git config --global abak.apitoken 0123456789yourf0123456789token
|
30
|
+
$ git remote add upstream git://github.com/github_user_name/project.git
|
31
|
+
|
32
|
+
### А если я использую прокси, как быть?
|
33
|
+
$ git config --global abak.proxy http://my-proxy.com:3129
|
34
|
+
|
35
|
+
Далее по приоритету идут переменные окружения. Сначала **http_proxy**, затем **HTTP_PROXY**
|
36
|
+
|
37
|
+
Т.е если вы используете переменные окружения, то просто не указывайте прокси в конфиге
|
38
|
+
|
39
|
+
### А если у меня есть баг-трэкер?
|
40
|
+
$ git config --global abak.tracker http://mytracker.com/ticket/
|
41
|
+
|
42
|
+
К указанному адресу будет доавлен номер тикета для формирования ссылок на задачи в описании пулл реквестов.
|
43
|
+
|
44
|
+
---
|
45
|
+
|
46
|
+
**Заметьте:** В конфиге git, значением *abak.apiuser* должен являться тот email адрес, под которым вы заходите на github
|
47
|
+
|
48
|
+
**Обратите внимание:** В данном контексте под **upstream** подразумевается адрес репозитория в который будут оформляться pull request. А репозиторием **origin** будет являться ваш форк
|
49
|
+
|
50
|
+
# С чего начать?
|
51
|
+
|
52
|
+
$ git request readycheck
|
53
|
+
|
54
|
+
или
|
55
|
+
|
56
|
+
$ git request help
|
57
|
+
|
58
|
+
**Примечание:** Вообще-то все комманды поддерживают опцию *--help*, но вот именно *git request --help* успевает перехватиться самим git и он конечно неодумевает как ему показать хэлп по внешней комманде
|
59
|
+
|
60
|
+
# Примеры использования
|
61
|
+
### Самый простой способ начать новую задачу:
|
62
|
+
|
63
|
+
$ git checkout develop
|
64
|
+
$ git request feature 'TASK-001'
|
65
|
+
$ touch 'hello.txt' && echo 'Hello world!' > hello.txt
|
66
|
+
$ git commit -a -m 'Hello world commit'
|
67
|
+
$ git request publish
|
68
|
+
|
69
|
+
Теперь то же самое, только словами:
|
70
|
+
|
71
|
+
* Переключимся в ветку develop
|
72
|
+
* Abak-flow создаст ветку, пригодную для оформления pull request (правила именования и правила самого реквеста)
|
73
|
+
* Простое создание нового файла
|
74
|
+
* Git процедуры добавления своих изменений в репозиторий
|
75
|
+
* Затем публикация вашей ветки на вашем форке (если таковая уже есть, то просто обновление), затем оформление pull request из этой ветки в соответствующую правилам ветку на upstream (в данном случае это будет ветка develop)
|
76
|
+
|
77
|
+
Для задач, которые должны быть выполнены в виде hotfix принцип тот же:
|
78
|
+
|
79
|
+
$ git checkout master
|
80
|
+
$ git request hotfix 'TASK-001'
|
81
|
+
$ …
|
82
|
+
$ git request publish
|
83
|
+
|
84
|
+
*На самом деле переключаться на master или develop в самом начале вовсе не обязательно, этот шаг был приведен для пущей ясности*
|
85
|
+
|
86
|
+
### Обновление ветки на удаленном репозитории:
|
87
|
+
|
88
|
+
$ git checkout feature/TASK-001
|
89
|
+
$ git request update
|
90
|
+
|
91
|
+
### Завершение текущей задачи:
|
92
|
+
Вообще, завершать задачу лучше только после того, как ваш pull request был принят. Почему? На самом деле по ряду причин. По умолчанию эта команда удаляет как вашу текущую ветку с задачей в локальном репозитории и в добавок ко всему - на вашем удаленном репозитории (форке)
|
93
|
+
|
94
|
+
$ git co feature/TASK-001
|
95
|
+
$ git request done
|
96
|
+
|
97
|
+
Чтобы оставить какую либо ветку в живых возможно напрямую указать, какую копию ветки **удалить**, локальную или же удаленную (на origin)
|
98
|
+
|
99
|
+
$ git co feature/TASK-001
|
100
|
+
$ git request done --origin
|
101
|
+
|
102
|
+
Или же так
|
103
|
+
|
104
|
+
$ git co feature/TASK-001
|
105
|
+
$ git request done --local
|
106
|
+
|
107
|
+
## Маленькие хитрости
|
108
|
+
Если сразу правильно именовать ветки, т.е ветку с задачей создавать с именем, такого формата TASK-001, то, в описание pull request автоматически вставится ссылка на задачу в jira, а в имя pull request сразу вставится название, состоящее из имени задачи, т.е TASK-001
|
109
|
+
|
110
|
+
## А помощь?
|
111
|
+
Многие команды имеют какие-то дополнительные опции. Но они нужны только в экзотических случаях. Но при любом раскладе подсказку и тонкий намек всегда можно получить воспользовавших такой командой:
|
112
|
+
|
113
|
+
$ git request done --help
|
114
|
+
|
115
|
+
# В заключении
|
116
|
+
Данный репозиторий и изложенные в нем идеи ни в коем случае не претендуют на идеал и совершенство. Это всего лишь узко заточенная комбинация гемов
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/bin/request
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'abak-flow/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'geometrialab-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}
|
13
|
+
|
14
|
+
# s.rubyforge_project = 'abak-flow'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
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']
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'hub'
|
22
|
+
s.add_runtime_dependency 'commander'
|
23
|
+
s.add_runtime_dependency 'octokit'
|
24
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Abak::Flow
|
2
|
+
class ::Hub::Runner
|
3
|
+
def execute
|
4
|
+
if args.noop?
|
5
|
+
puts commands
|
6
|
+
elsif not args.skip?
|
7
|
+
if args.chained?
|
8
|
+
execute_command_chain
|
9
|
+
else
|
10
|
+
%x{#{args.to_exec.join(' ')}}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ::Hub::Commands
|
17
|
+
def pull_request(args)
|
18
|
+
args.shift
|
19
|
+
options = { }
|
20
|
+
force = explicit_owner = false
|
21
|
+
base_project = local_repo.main_project
|
22
|
+
head_project = local_repo.current_project
|
23
|
+
|
24
|
+
from_github_ref = lambda do |ref, context_project|
|
25
|
+
if ref.index(':')
|
26
|
+
owner, ref = ref.split(':', 2)
|
27
|
+
project = github_project(context_project.name, owner)
|
28
|
+
end
|
29
|
+
[project || context_project, ref]
|
30
|
+
end
|
31
|
+
|
32
|
+
while arg = args.shift
|
33
|
+
case arg
|
34
|
+
when '-f'
|
35
|
+
force = true
|
36
|
+
when '-b'
|
37
|
+
base_project, options[:base] = from_github_ref.call(args.shift, base_project)
|
38
|
+
when '-h'
|
39
|
+
head = args.shift
|
40
|
+
explicit_owner = !!head.index(':')
|
41
|
+
head_project, options[:head] = from_github_ref.call(head, head_project)
|
42
|
+
when '-i'
|
43
|
+
options[:issue] = args.shift
|
44
|
+
when '-d'
|
45
|
+
options[:body] = args.shift
|
46
|
+
else
|
47
|
+
if url = resolve_github_url(arg) and url.project_path =~ /^issues\/(\d+)/
|
48
|
+
options[:issue] = $1
|
49
|
+
base_project = url.project
|
50
|
+
elsif !options[:title] then options[:title] = arg
|
51
|
+
else
|
52
|
+
abort "invalid argument: #{arg}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
options[:project] = base_project
|
58
|
+
options[:base] ||= master_branch.short_name
|
59
|
+
|
60
|
+
if tracked_branch = options[:head].nil? && current_branch.upstream
|
61
|
+
if base_project == head_project and tracked_branch.short_name == options[:base]
|
62
|
+
$stderr.puts "Aborted: head branch is the same as base (#{options[:base].inspect})"
|
63
|
+
warn "(use `-h <branch>` to specify an explicit pull request head)"
|
64
|
+
abort
|
65
|
+
end
|
66
|
+
end
|
67
|
+
options[:head] ||= (tracked_branch || current_branch).short_name
|
68
|
+
|
69
|
+
# when no tracking, assume remote branch is published under active user's fork
|
70
|
+
user = github_user(true, head_project.host)
|
71
|
+
if head_project.owner != user and !tracked_branch and !explicit_owner
|
72
|
+
head_project = head_project.owned_by(user)
|
73
|
+
end
|
74
|
+
|
75
|
+
remote_branch = "#{head_project.remote}/#{options[:head]}"
|
76
|
+
options[:head] = "#{head_project.owner}:#{options[:head]}"
|
77
|
+
|
78
|
+
if !force and tracked_branch and local_commits = git_command("rev-list --cherry #{remote_branch}...")
|
79
|
+
$stderr.puts "Aborted: #{local_commits.split("\n").size} commits are not yet pushed to #{remote_branch}"
|
80
|
+
warn "(use `-f` to force submit a pull request anyway)"
|
81
|
+
abort
|
82
|
+
end
|
83
|
+
|
84
|
+
if args.noop?
|
85
|
+
puts "Would reqest a pull to #{base_project.owner}:#{options[:base]} from #{options[:head]}"
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
89
|
+
unless options[:title] or options[:issue]
|
90
|
+
base_branch = "#{base_project.remote}/#{options[:base]}"
|
91
|
+
changes = git_command "log --no-color --pretty=medium --cherry %s...%s" %
|
92
|
+
[base_branch, remote_branch]
|
93
|
+
|
94
|
+
options[:title], options[:body] = pullrequest_editmsg(changes) { |msg|
|
95
|
+
msg.puts "# Requesting a pull to #{base_project.owner}:#{options[:base]} from #{options[:head]}"
|
96
|
+
msg.puts "#"
|
97
|
+
msg.puts "# Write a message for this pull request. The first block"
|
98
|
+
msg.puts "# of text is the title and the rest is description."
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
pull = create_pullrequest(options)
|
103
|
+
|
104
|
+
args.executable = 'echo'
|
105
|
+
args.replace [pull['html_url']]
|
106
|
+
rescue HTTPExceptions
|
107
|
+
display_http_exception("creating pull request", $!.response)
|
108
|
+
exit 1
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Abak::Flow
|
3
|
+
# @TODO Сделать класс, в котором собрать общие куски из задач
|
4
|
+
|
5
|
+
program :name, 'Утилита для оформления pull request на github.com'
|
6
|
+
program :version, Abak::Flow::VERSION
|
7
|
+
program :description, 'Утилита, заточенная под git-flow но с использованием github.com'
|
8
|
+
|
9
|
+
default_command :help
|
10
|
+
command :publish do |c|
|
11
|
+
c.syntax = 'git request publish <Заголовок>'
|
12
|
+
c.description = 'Оформить pull request из текущей ветки (feature -> develop, hotfix -> master)'
|
13
|
+
|
14
|
+
# Опции нужны, если человек хочет запушить ветку, с именем отличным от стандарта
|
15
|
+
c.option '--head STRING', String, 'Имя ветки, которую нужно принять в качестве изменений'
|
16
|
+
c.option '--base STRING', String, 'Имя ветки, в которую нужно принять изменения'
|
17
|
+
|
18
|
+
c.action do |args, options|
|
19
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
20
|
+
|
21
|
+
request_rules = {:feature => :develop, :hotfix => :master}
|
22
|
+
|
23
|
+
repository = Hub::Commands.send :local_repo
|
24
|
+
current_branch = repository.current_branch.short_name
|
25
|
+
remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
|
26
|
+
|
27
|
+
title = args.first.to_s.strip
|
28
|
+
title = task if task =~ /^\w+\-\d{1,}$/ && title.empty?
|
29
|
+
|
30
|
+
tracker_url = Hub::Commands.send(:git_reader).read_config('abak.tracker')
|
31
|
+
api_user = Hub::Commands.send(:git_reader).read_config('abak.apiuser')
|
32
|
+
api_token = Hub::Commands.send(:git_reader).read_config('abak.apitoken')
|
33
|
+
config_proxy = Hub::Commands.send(:git_reader).read_config('abak.proxy')
|
34
|
+
env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
35
|
+
|
36
|
+
client_opts = {:proxy => config_proxy || env_proxy} if config_proxy || env_proxy
|
37
|
+
client_opts ||= {}
|
38
|
+
|
39
|
+
api_client = Octokit::Client.new({:login => api_user, :oauth_token => api_token}.merge(client_opts))
|
40
|
+
|
41
|
+
# Проверим, что мы не в мастере или девелопе
|
42
|
+
if [:master, :develop].include? current_branch.to_sym
|
43
|
+
say color('Нельзя делать pull request из меток master или develop', :error).to_s
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
# Проверим, что у нас настроен origin
|
48
|
+
if repository.remote_by_name('origin').nil?
|
49
|
+
say color('Необходимо настроить репозиторий origin (форк) для текущего пользователя', :error).to_s
|
50
|
+
say color('=> git remote add origin https://Developer@github.com/abak-press/sample.git', :info).to_s
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
# Проверим, что у нас настроен upstream
|
55
|
+
if repository.remote_by_name('upstream').nil?
|
56
|
+
say color('Необходимо настроить репозиторий upstream (главный) для текущего пользователя', :error).to_s
|
57
|
+
say color('=> git remote add upstream https://Developer@github.com/abak-press/sample.git', :info).to_s
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
if title.empty?
|
62
|
+
say color('Пожалуйста, укажите что-нибудь для заголовка pull request, например номер вашей задачи вот так:', :error).to_s
|
63
|
+
say color('=> git request publish "PC-001"', :info).to_s
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
|
67
|
+
# Проверим, что у нас указан апи юзер
|
68
|
+
if api_user.empty?
|
69
|
+
say color('Необходимо указать своего пользователя API github', :error).to_s
|
70
|
+
say color('=> https://github.com/Strech/abak-flow/blob/master/README.md', :info).to_s
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
|
74
|
+
# Проверим, что у нас указан токен
|
75
|
+
if api_token.empty?
|
76
|
+
say color('Необходимо указать токен своего пользователя API github', :error).to_s
|
77
|
+
say color('=> https://github.com/Strech/abak-flow/blob/master/README.md', :info).to_s
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
|
81
|
+
upstream_project = repository.remote_by_name('upstream').project
|
82
|
+
|
83
|
+
# Расставим ветки согласно правилам
|
84
|
+
head = "#{repository.repo_owner}:#{current_branch}"
|
85
|
+
base = "#{repository.remote_by_name('upstream').project.owner}:#{request_rules.fetch(remote_branch.to_sym, '')}"
|
86
|
+
|
87
|
+
head = options.head unless options.head.nil?
|
88
|
+
base = options.base unless options.base.nil?
|
89
|
+
|
90
|
+
# Запушим текущую ветку на origin
|
91
|
+
# TODO Может быть лучше достать дерективу конфига origin?
|
92
|
+
say "=> Обновляю ветку #{current_branch} на origin"
|
93
|
+
Hub::Runner.execute('push', 'origin', current_branch)
|
94
|
+
|
95
|
+
# Запостим pull request на upstream
|
96
|
+
body = tracker_url + task if task =~ /^\w+\-\d{1,}$/
|
97
|
+
body ||= 'Я забыл какая это задача :('
|
98
|
+
|
99
|
+
say '=> Делаю pull request на upstream'
|
100
|
+
result = api_client.create_pull_request("#{upstream_project.owner}/#{upstream_project.name}", base, head, title, body)
|
101
|
+
say result._links.self.href
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
command :update do |c|
|
106
|
+
c.syntax = 'git request update'
|
107
|
+
c.description = 'Обновить ветку на удаленном (origin) репозитории'
|
108
|
+
|
109
|
+
c.option '--branch STRING', String, 'Имя ветки, которую нужно обновить'
|
110
|
+
|
111
|
+
c.action do |args, options|
|
112
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
113
|
+
|
114
|
+
repository = Hub::Commands.send :local_repo
|
115
|
+
current_branch = repository.current_branch.short_name
|
116
|
+
|
117
|
+
# Проверим, что у нас настроен origin
|
118
|
+
if repository.remote_by_name('origin').nil?
|
119
|
+
say color('Необходимо настроить репозиторий origin (форк) для текущего пользователя', :error).to_s
|
120
|
+
say color('=> git remote add origin https://Developer@github.com/abak-press/sample.git', :info).to_s
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
|
124
|
+
# Запушим текущую ветку на origin
|
125
|
+
branch = options.branch || current_branch
|
126
|
+
say "=> Обновляю ветку #{branch} на origin"
|
127
|
+
Hub::Runner.execute('push', 'origin', branch)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
command :feature do |c|
|
132
|
+
c.syntax = 'git request feature <Название задачи>'
|
133
|
+
c.description = 'Создать ветку для выполнения задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
134
|
+
|
135
|
+
c.action do |args, options|
|
136
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
137
|
+
|
138
|
+
task = args.shift.to_s
|
139
|
+
|
140
|
+
if task.empty?
|
141
|
+
say color('Необходимо указать имя задачи, а лучше всего ее номер из jira', :error).to_s
|
142
|
+
exit
|
143
|
+
end
|
144
|
+
|
145
|
+
unless task =~ /^\w+\-\d{1,}$/
|
146
|
+
say '=> Вы приняли верное решение :)' && exit if agree("Лучше всего завести задачу с именем примерно такого формата PC-001, может попробуем заново? [y/n]:")
|
147
|
+
end
|
148
|
+
|
149
|
+
Hub::Runner.execute('flow', 'feature', 'start', task)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
command :hotfix do |c|
|
154
|
+
c.syntax = 'git request hotfix <Название задачи>'
|
155
|
+
c.description = 'Создать ветку для выполнения bugfix задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
156
|
+
|
157
|
+
c.action do |args, options|
|
158
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
159
|
+
|
160
|
+
task = args.shift.to_s
|
161
|
+
|
162
|
+
if task.empty?
|
163
|
+
say color('Необходимо указать имя задачи, а лучше всего ее номер из jira', :error).to_s
|
164
|
+
exit
|
165
|
+
end
|
166
|
+
|
167
|
+
unless task =~ /^\w+\-\d{1,}$/
|
168
|
+
say '=> Вы приняли верное решение :)' && exit if agree("Лучше всего завести задачу с именем примерно такого формата PC-001, может попробуем заново? [y/n]:")
|
169
|
+
end
|
170
|
+
|
171
|
+
Hub::Runner.execute('flow', 'hotfix', 'start', task)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
command :done do |c|
|
176
|
+
c.syntax = 'git request done'
|
177
|
+
c.description = 'Завершить pull request. По умолчанию удаляются ветки как локальная (local), так и удаленная (origin)'
|
178
|
+
|
179
|
+
c.option '--branch STRING', String, 'Имя ветки pull request которой нужно закрыть'
|
180
|
+
c.option '--all', 'Удаляет ветку в локальном репозитории и в удалнном (local + origin) (по умолчанию)'
|
181
|
+
c.option '--local', 'Удаляет ветку только в локальном репозитории (local)'
|
182
|
+
c.option '--origin', 'Удаляет ветку в удаленном репозитории (origin)'
|
183
|
+
|
184
|
+
c.action do |args, options|
|
185
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
186
|
+
|
187
|
+
repository = Hub::Commands.send :local_repo
|
188
|
+
current_branch = repository.current_branch.short_name
|
189
|
+
branch = options.branch || current_branch
|
190
|
+
|
191
|
+
type = :all
|
192
|
+
if [options.local, options.origin].compact.count == 1
|
193
|
+
type = options.local ? :local : :origin
|
194
|
+
end
|
195
|
+
|
196
|
+
if [:master, :develop].include? branch.to_sym
|
197
|
+
say color('Извините, но нельзя удалить ветку develop или master', :error).to_s
|
198
|
+
exit
|
199
|
+
end
|
200
|
+
|
201
|
+
warning = "Внимание! Alarm! Danger! Achtung\nЕсли вы удалите ветку на удаленном репозитории, а ваш pull request еще не приняли, вы рискуете потерять проделанную работу.\nВы уверены, что хотите продолжить?"
|
202
|
+
if [:all, :origin].include?(type)
|
203
|
+
say '=> Вы приняли верное решение :)' && exit unless agree("#{warning} [y/n]:")
|
204
|
+
end
|
205
|
+
|
206
|
+
# @TODO Проверку на наличие ветки на origin
|
207
|
+
if [:all, :origin].include? type
|
208
|
+
say "=> Удаляю ветку #{branch} на origin"
|
209
|
+
Hub::Runner.execute('push', repository.main_project.remote.name, ':' + branch)
|
210
|
+
end
|
211
|
+
|
212
|
+
if [:all, :local].include? type
|
213
|
+
remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
|
214
|
+
|
215
|
+
say "=> Удаляю локальную ветку #{branch}"
|
216
|
+
Hub::Runner.execute('checkout', 'develop')
|
217
|
+
Hub::Runner.execute('branch', '-D', branch)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# TODO Отрефакторить эту какашку
|
223
|
+
command :readycheck do |c|
|
224
|
+
c.syntax = 'git request readycheck'
|
225
|
+
c.description = 'Проверить все ли настроено для работы с github и удаленным (origin) репозиторием'
|
226
|
+
|
227
|
+
c.action do |args, options|
|
228
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
229
|
+
repository = Hub::Commands.send :local_repo
|
230
|
+
current_branch = repository.current_branch.short_name
|
231
|
+
|
232
|
+
api_user = Hub::Commands.send(:git_reader).read_config('abak.apiuser').to_s
|
233
|
+
api_token = Hub::Commands.send(:git_reader).read_config('abak.apitoken').to_s
|
234
|
+
config_proxy = Hub::Commands.send(:git_reader).read_config('abak.proxy')
|
235
|
+
env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
236
|
+
|
237
|
+
errors = []
|
238
|
+
|
239
|
+
# Проверим, что у нас настроен origin
|
240
|
+
if repository.remote_by_name('origin').nil?
|
241
|
+
errors << [
|
242
|
+
'Необходимо настроить репозиторий origin (форк) для текущего пользователя',
|
243
|
+
'=> git remote add origin https://Developer@github.com/abak-press/sample.git'
|
244
|
+
]
|
245
|
+
end
|
246
|
+
|
247
|
+
# Проверим, что у нас настроен upstream
|
248
|
+
if repository.remote_by_name('upstream').nil?
|
249
|
+
errors << [
|
250
|
+
'Необходимо настроить репозиторий upstream (главный) для текущего пользователя',
|
251
|
+
'=> git remote add upstream https://Developer@github.com/abak-press/sample.git'
|
252
|
+
]
|
253
|
+
end
|
254
|
+
|
255
|
+
# Проверим, что у нас указан апи юзер
|
256
|
+
if api_user.empty?
|
257
|
+
errors << [
|
258
|
+
'Необходимо указать своего пользователя API github',
|
259
|
+
'=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
260
|
+
]
|
261
|
+
end
|
262
|
+
|
263
|
+
# Проверим, что у нас указан токен
|
264
|
+
if api_token.empty?
|
265
|
+
errors << [
|
266
|
+
'Необходимо указать токен своего пользователя API github',
|
267
|
+
'=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
268
|
+
]
|
269
|
+
end
|
270
|
+
|
271
|
+
if config_proxy || env_proxy
|
272
|
+
message = "== В качестве прокси будет установлено значение #{config_proxy || env_proxy} =="
|
273
|
+
say color('=' * message.length, :info).to_s
|
274
|
+
say color(message, :info).to_s
|
275
|
+
say color('=' * message.length + "\n", :info).to_s
|
276
|
+
end
|
277
|
+
|
278
|
+
errors.each do |error|
|
279
|
+
say "#{color(error.first, :error)}\n#{color(error.last, :info)}"
|
280
|
+
end
|
281
|
+
|
282
|
+
say color('Хм ... кажется у вас все готово к работе', :debug).to_s if errors.count.zero?
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
data/lib/abak-flow.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geometrialab-abak-flow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Strech (aka Sergey Fedorov)
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-05-21 00:00:00 +04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: hub
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: commander
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: octokit
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
description: !binary |
|
57
|
+
0J/RgNC+0YHRgtC+0Lkg0L3QsNCx0L7RgCDQv9GA0LDQstC40Lsg0Lgg0LrQ
|
58
|
+
vtC80LzQsNC90LQsINC30LDRgtC+0YfQtdC90YvRhSDQtNC70Y8g0YDQsNCx
|
59
|
+
0L7RgtGLINCyIGdpdC1mbG93INGBINC40YHQv9C+0LvRjNC30L7QstCw0L3Q
|
60
|
+
uNC1INCyINC60LDRh9C10YHRgtCy0LUg0YPQtNCw0LvQtdC90L3QvtCz0L4g
|
61
|
+
0YDQtdC/0L7Qt9C40YLQvtGA0LjRjyBnaXRodWI=
|
62
|
+
|
63
|
+
email:
|
64
|
+
- oni.strech@gmail.com
|
65
|
+
executables:
|
66
|
+
- request
|
67
|
+
extensions: []
|
68
|
+
|
69
|
+
extra_rdoc_files: []
|
70
|
+
|
71
|
+
files:
|
72
|
+
- .gitignore
|
73
|
+
- Gemfile
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- VERSION
|
77
|
+
- bin/request
|
78
|
+
- geometrialab-abak-flow.gemspec
|
79
|
+
- lib/abak-flow.rb
|
80
|
+
- lib/abak-flow/hub_extensions.rb
|
81
|
+
- lib/abak-flow/request.rb
|
82
|
+
- lib/abak-flow/version.rb
|
83
|
+
has_rdoc: true
|
84
|
+
homepage: https://github.com/Strech/abak-flow
|
85
|
+
licenses: []
|
86
|
+
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.3.6
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: !binary |
|
113
|
+
0KHQvtCy0LzQtdGJ0LXQvdC40LUgMi3RhSDQv9C+0LTRhdC+0LTQvtCyINGA
|
114
|
+
0LDQt9GA0LDQsdC+0YLQutC4IEdpdC1mbG93ICYgR2l0aHViLWZsb3c=
|
115
|
+
|
116
|
+
test_files: []
|
117
|
+
|