no message
This commit is contained in:
parent
56bb9b5699
commit
0adfc39d8d
7 changed files with 758 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -6,3 +6,5 @@ output/Scratch/en
|
|||
output/Scratch/fr
|
||||
output/Scratch/map.yrf
|
||||
tmp/
|
||||
recupen.pl
|
||||
recupfr.pl
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-02-23T10:09:52+02:00
|
||||
title: When regexp is not the best solution
|
||||
multiTitle:
|
||||
fr: When regexp is not the best solution
|
||||
en: When regexp is not the best solution
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- programming
|
||||
- regexp
|
||||
- regular expression
|
||||
- extension
|
||||
- file
|
||||
|
||||
-----
|
||||
|
||||
Regular expression are really useful. Unfortunately, they are not always the best way of doing things.
|
||||
Particularly when transformations you want to make are easy.
|
||||
|
||||
I wanted to know how to get file extension from filename the fastest way possible. There is 3 natural way of doing this:
|
||||
|
||||
<div><code class="ruby">
|
||||
# regexp
|
||||
str.match(/[^.]*$/);
|
||||
ext=$&
|
||||
|
||||
# split
|
||||
ext=str.split('.')[-1]
|
||||
|
||||
# File module
|
||||
ext=File.extname(str)
|
||||
</code></div>
|
||||
|
||||
At first sight I believed that the regexp should be faster than the split because it could be many `.` in a filename. But in reality, most of time there is only one dot and I realized the split will be faster. But not the fastest way. There is a function dedicated to this work in the `File` module.
|
||||
|
||||
Here is the Benchmark ruby code:
|
||||
|
||||
<div><code class="ruby" file="regex_benchmark_ext.rb">
|
||||
#!/usr/bin/env ruby
|
||||
require 'benchmark'
|
||||
n=80000
|
||||
tab=[ '/accounts/user.json',
|
||||
'/accounts/user.xml',
|
||||
'/user/titi/blog/toto.json',
|
||||
'/user/titi/blog/toto.xml' ]
|
||||
|
||||
puts "Get extname"
|
||||
Benchmark.bm do |x|
|
||||
x.report("regexp:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
str.match(/[^.]*$/);
|
||||
ext=$&;
|
||||
end }
|
||||
x.report(" split:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=str.split('.')[-1] ;
|
||||
end }
|
||||
x.report(" File:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=File.extname(str);
|
||||
end }
|
||||
end
|
||||
</code></div>
|
||||
|
||||
And here is the result
|
||||
|
||||
<pre class="twilight">
|
||||
Get extname
|
||||
user system total real
|
||||
regexp: 2.550000 0.020000 2.570000 ( 2.693407)
|
||||
split: 1.080000 0.050000 1.130000 ( 1.190408)
|
||||
File: 0.640000 0.030000 0.670000 ( 0.717748)
|
||||
</pre>
|
||||
|
||||
Conclusion of this benchmark, dedicated function are better than your way of doing stuff (most of time).
|
||||
|
||||
## file path without the extension.
|
||||
|
||||
<div><code class="ruby" file="regex_benchmark_strip.rb">
|
||||
#!/usr/bin/env ruby
|
||||
require 'benchmark'
|
||||
n=80000
|
||||
tab=[ '/accounts/user.json',
|
||||
'/accounts/user.xml',
|
||||
'/user/titi/blog/toto.json',
|
||||
'/user/titi/blog/toto.xml' ]
|
||||
|
||||
puts "remove extension"
|
||||
Benchmark.bm do |x|
|
||||
x.report(" File:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
path=File.expand_path(str,File.basename(str,File.extname(str)));
|
||||
end }
|
||||
x.report("chomp:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=File.extname(str);
|
||||
path=str.chomp(ext);
|
||||
end }
|
||||
end
|
||||
</code></div>
|
||||
|
||||
and here is the result:
|
||||
|
||||
<pre class="twilight">
|
||||
remove extension
|
||||
user system total real
|
||||
File: 0.970000 0.060000 1.030000 ( 1.081398)
|
||||
chomp: 0.820000 0.040000 0.860000 ( 0.947432)
|
||||
</pre>
|
||||
|
||||
Conclusion of the second benchmark. One simple function is better than three dedicated functions. No surprise, but it is good to know.
|
78
content/html/en/blog/2010-03-22-Git-Tips.md
Normal file
78
content/html/en/blog/2010-03-22-Git-Tips.md
Normal file
|
@ -0,0 +1,78 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-03-22T10:42:27+02:00
|
||||
title: Git Tips
|
||||
multiTitle:
|
||||
fr: Git Tips
|
||||
en: Git Tips
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- git
|
||||
- tip
|
||||
|
||||
-----
|
||||
|
||||
## clone from github behind an evil firewall
|
||||
|
||||
Standard:
|
||||
|
||||
<div><code class="zsh">
|
||||
git clone git@github.com:yogsototh/project.git
|
||||
</code></div>
|
||||
|
||||
Using HTTPS port:
|
||||
|
||||
<div><code class="zsh">
|
||||
git clone git+ssh://git@github.com:443/yogsototh/project.git
|
||||
</code></div>
|
||||
|
||||
## clone all branches
|
||||
|
||||
`git clone` can only fetch the master branch.
|
||||
|
||||
If you don't have much branches, you can simply use clone your project and then use the following command:
|
||||
|
||||
<div><code class="zsh">
|
||||
git branch --track local_branch remote_branch
|
||||
</code></div>
|
||||
|
||||
for example:
|
||||
<div><code class="zsh">
|
||||
$ git clone git@github:yogsototh/example.git
|
||||
$ git branch
|
||||
master *
|
||||
$ git branch -a
|
||||
master *
|
||||
remotes/origin/HEAD -> origin/master
|
||||
remotes/origin/experimental
|
||||
$ git branch --track experimental remotes/origin/experimental
|
||||
$ git branch
|
||||
master *
|
||||
experimental
|
||||
</code></div>
|
||||
|
||||
If you have many branches it can be useful to use the following *script*/*long command line*.
|
||||
|
||||
<div><code class="zsh">
|
||||
# first clone your project
|
||||
$ git clone git@github.com:yogsototh/project.git
|
||||
|
||||
# copy all branches
|
||||
$ zsh
|
||||
$ cd project
|
||||
$ for br in $( git br -a ); do
|
||||
case $br in
|
||||
remotes/*) print $br ;
|
||||
case ${br:t} in
|
||||
master|HEAD) continue ;;
|
||||
*) git branch --track ${br:t} $br ;;
|
||||
esac ;;
|
||||
esac
|
||||
done
|
||||
</code></div>
|
182
content/html/en/blog/2010-03-23-Encapsulate-git.md
Normal file
182
content/html/en/blog/2010-03-23-Encapsulate-git.md
Normal file
|
@ -0,0 +1,182 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-03-23T22:37:36+02:00
|
||||
title: Encapsulate git
|
||||
multiTitle:
|
||||
fr: Encapsuler git
|
||||
en: Encapsulate git
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- git
|
||||
- protection
|
||||
- branches
|
||||
- diverged
|
||||
|
||||
-----
|
||||
|
||||
<div class="small">
|
||||
Here is a solution to maintain divergent branches in git. Because it is easy to merge by mistake. I give a script that encapsulate git in order to forbid some merge and warn you some merge should be dangerous.
|
||||
</div>
|
||||
|
||||
## how to protect against your own dumb
|
||||
|
||||
I work on a project in which some of my git branches should remain divergent. And divergences should grow.
|
||||
|
||||
I also use some branch to contain what is common between projects.
|
||||
|
||||
Say I have some branches:
|
||||
|
||||
master: common to all branches
|
||||
dev: branch devoted to unstable development
|
||||
client: branch with features for all client but not general enough for master
|
||||
clientA: project adapted for client A
|
||||
clientB: project adapted for client B
|
||||
|
||||
Here how I want to work:
|
||||
|
||||
<%= blogimage("Dynamic branching","dynamic_branching.png") %>
|
||||
|
||||
And more precisely the branch hierarchy:
|
||||
|
||||
<%= blogimage("Branch hierarchy","branch_hierarchy.png") %>
|
||||
|
||||
An arrow from A to B means, you can merge A in B. If there is no arrow from A to B that means it is *forbidden* to merge A in B. Here is the corresponding rubycode:
|
||||
|
||||
<div><code class="ruby">
|
||||
$architecture={
|
||||
:master => [ :dev, :client ],
|
||||
:dev => [ :master ],
|
||||
:client => [ :clientA, :clientB ] }
|
||||
</code></div>
|
||||
|
||||
Having a `:master => [ :dev, :client ]` means you can merge `master` branch into `dev` and `client`.
|
||||
|
||||
If by mistake I make a `git checkout master && git merge clientA`, I made a mistake. This is why I made a script which encapsulate the git behaviour to dodge this kind of mistake.
|
||||
|
||||
But this script do far more than that. It also merge from top to down. The action `allmerges` will do:
|
||||
|
||||
<div><code class="zsh">
|
||||
git co dev && git merge master
|
||||
git co client && git merge master
|
||||
git co clientA && git merge client
|
||||
git co clientB && git merge client
|
||||
</code></div>
|
||||
|
||||
That means, I can update all branches. The algorithm will not make loop even if there is a cycle in the branch hierarchy.
|
||||
|
||||
Here it is:
|
||||
|
||||
<div class="small"><code class="ruby" file="eng">
|
||||
#!/usr/bin/env ruby
|
||||
# encoding: utf-8
|
||||
|
||||
# architecture
|
||||
#
|
||||
# master <-> dev
|
||||
# master -> client
|
||||
# clien -> clientA | clientB
|
||||
#
|
||||
# merge using two of these branches should be
|
||||
# restricted to these rules
|
||||
# merge to one of these branch and an unknown one should
|
||||
# raise a warning, and may the option to add this new branch
|
||||
# to the hierarchy
|
||||
|
||||
$architecture={
|
||||
:master => [ :dev, :client ],
|
||||
:dev => [ :master ],
|
||||
:client => [ :clientA, :clientB ] }
|
||||
|
||||
def get_current_branch()
|
||||
(`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
|
||||
end
|
||||
|
||||
if ARGV.length == 0
|
||||
puts %{usage: $0:t [git_command or local_command]
|
||||
|
||||
local commands:
|
||||
allmerges: merge from top to down}
|
||||
exit 0
|
||||
end
|
||||
|
||||
require 'set'
|
||||
$known_branches=Set.new
|
||||
$architecture.each do |k,v|
|
||||
$known_branches.add(k)
|
||||
v.each { |b| $known_branches.add(b) }
|
||||
end
|
||||
|
||||
def rec_merge(branch)
|
||||
if $architecture[branch].nil?
|
||||
return
|
||||
end
|
||||
$architecture[branch].each do |b|
|
||||
if $flag.has_key?(b.to_s + branch.to_s)
|
||||
next
|
||||
end
|
||||
flagname=branch.to_s + b.to_s
|
||||
if $flag.has_key?(flagname)
|
||||
next
|
||||
end
|
||||
if system %{eng checkout #{b}}
|
||||
if get_current_branch != b
|
||||
puts "Can't checkout to #{b}"
|
||||
exit 2
|
||||
end
|
||||
if system %{eng merge #{branch}}
|
||||
$flag[flagname]=true
|
||||
rec_merge(b)
|
||||
else
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def do_all_merges
|
||||
puts 'Will merge from father to sons'
|
||||
current_branch=get_current_branch
|
||||
$flag={}
|
||||
rec_merge(:master)
|
||||
system %{git co #{current_branch}}
|
||||
end
|
||||
|
||||
def do_merge
|
||||
current_branch=get_current_branch
|
||||
src_branch=ARGV[1].intern
|
||||
puts %{do_merge: #{src_branch} => #{current_branch}}
|
||||
if $known_branches.include?(current_branch)
|
||||
if $known_branches.include?(src_branch)
|
||||
if $architecture.has_key?(src_branch) and
|
||||
$architecture[src_branch].include?(current_branch)
|
||||
system %{git merge #{src_branch}}
|
||||
else
|
||||
puts %{Forbidden merge: #{src_branch} => #{current_branch}}
|
||||
end
|
||||
else
|
||||
puts %{Warning! #{src_branch} not mentionned in rb configuration}
|
||||
sleep 2
|
||||
f system %{git merge #{src_branch}}
|
||||
puts %{Warning! #{src_branch} not mentionned in rb configuration}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
case ARGV[0]
|
||||
when 'allmerges' then do_all_merges
|
||||
when 'merge' then do_merge
|
||||
else system %{git #{ARGV.join(' ')}}
|
||||
end
|
||||
</code></div>
|
||||
|
||||
All you need to do to make it work is simply to copy eng in a directory contained in your PATH.
|
||||
|
||||
Of course try to use as few as possible `cherry-pick` and `rebase`. This script was intended to work with workflow using `pull` and `merge`.
|
|
@ -0,0 +1,118 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-02-23T10:09:52+02:00
|
||||
title: When regexp is not the best solution
|
||||
multiTitle:
|
||||
fr: When regexp is not the best solution
|
||||
en: When regexp is not the best solution
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- programming
|
||||
- regexp
|
||||
- regular expression
|
||||
- extension
|
||||
- file
|
||||
|
||||
-----
|
||||
|
||||
Regular expression are really useful. Unfortunately, they are not always the best way of doing things.
|
||||
Particularly when transformations you want to make are easy.
|
||||
|
||||
I wanted to know how to get file extension from filename the fastest way possible. There is 3 natural way of doing this:
|
||||
|
||||
<div><code class="ruby">
|
||||
# regexp
|
||||
str.match(/[^.]*$/);
|
||||
ext=$&
|
||||
|
||||
# split
|
||||
ext=str.split('.')[-1]
|
||||
|
||||
# File module
|
||||
ext=File.extname(str)
|
||||
</code></div>
|
||||
|
||||
At first sight I believed that the regexp should be faster than the split because it could be many `.` in a filename. But in reality, most of time there is only one dot and I realized the split will be faster. But not the fastest way. There is a function dedicated to this work in the `File` module.
|
||||
|
||||
Here is the Benchmark ruby code:
|
||||
|
||||
<div><code class="ruby" file="regex_benchmark_ext.rb">
|
||||
#!/usr/bin/env ruby
|
||||
require 'benchmark'
|
||||
n=80000
|
||||
tab=[ '/accounts/user.json',
|
||||
'/accounts/user.xml',
|
||||
'/user/titi/blog/toto.json',
|
||||
'/user/titi/blog/toto.xml' ]
|
||||
|
||||
puts "Get extname"
|
||||
Benchmark.bm do |x|
|
||||
x.report("regexp:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
str.match(/[^.]*$/);
|
||||
ext=$&;
|
||||
end }
|
||||
x.report(" split:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=str.split('.')[-1] ;
|
||||
end }
|
||||
x.report(" File:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=File.extname(str);
|
||||
end }
|
||||
end
|
||||
</code></div>
|
||||
|
||||
And here is the result
|
||||
|
||||
<pre class="twilight">
|
||||
Get extname
|
||||
user system total real
|
||||
regexp: 2.550000 0.020000 2.570000 ( 2.693407)
|
||||
split: 1.080000 0.050000 1.130000 ( 1.190408)
|
||||
File: 0.640000 0.030000 0.670000 ( 0.717748)
|
||||
</pre>
|
||||
|
||||
Conclusion of this benchmark, dedicated function are better than your way of doing stuff (most of time).
|
||||
|
||||
## file path without the extension.
|
||||
|
||||
<div><code class="ruby" file="regex_benchmark_strip.rb">
|
||||
#!/usr/bin/env ruby
|
||||
require 'benchmark'
|
||||
n=80000
|
||||
tab=[ '/accounts/user.json',
|
||||
'/accounts/user.xml',
|
||||
'/user/titi/blog/toto.json',
|
||||
'/user/titi/blog/toto.xml' ]
|
||||
|
||||
puts "remove extension"
|
||||
Benchmark.bm do |x|
|
||||
x.report(" File:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
path=File.expand_path(str,File.basename(str,File.extname(str)));
|
||||
end }
|
||||
x.report("chomp:") { n.times do
|
||||
str=tab[rand(4)];
|
||||
ext=File.extname(str);
|
||||
path=str.chomp(ext);
|
||||
end }
|
||||
end
|
||||
</code></div>
|
||||
|
||||
and here is the result:
|
||||
|
||||
<pre class="twilight">
|
||||
remove extension
|
||||
user system total real
|
||||
File: 0.970000 0.060000 1.030000 ( 1.081398)
|
||||
chomp: 0.820000 0.040000 0.860000 ( 0.947432)
|
||||
</pre>
|
||||
|
||||
Conclusion of the second benchmark. One simple function is better than three dedicated functions. No surprise, but it is good to know.
|
78
content/html/fr/blog/2010-03-22-Git-Tips.md
Normal file
78
content/html/fr/blog/2010-03-22-Git-Tips.md
Normal file
|
@ -0,0 +1,78 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-03-22T10:42:27+02:00
|
||||
title: Git Tips
|
||||
multiTitle:
|
||||
fr: Git Tips
|
||||
en: Git Tips
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- git
|
||||
- tip
|
||||
|
||||
-----
|
||||
|
||||
## clone from github behind an evil firewall
|
||||
|
||||
Standard:
|
||||
|
||||
<div><code class="zsh">
|
||||
git clone git@github.com:yogsototh/project.git
|
||||
</code></div>
|
||||
|
||||
Using HTTPS port:
|
||||
|
||||
<div><code class="zsh">
|
||||
git clone git+ssh://git@github.com:443/yogsototh/project.git
|
||||
</code></div>
|
||||
|
||||
## clone all branches
|
||||
|
||||
`git clone` can only fetch the master branch.
|
||||
|
||||
If you don't have much branches, you can simply use clone your project and then use the following command:
|
||||
|
||||
<div><code class="zsh">
|
||||
git branch --track local_branch remote_branch
|
||||
</code></div>
|
||||
|
||||
for example:
|
||||
<div><code class="zsh">
|
||||
$ git clone git@github:yogsototh/example.git
|
||||
$ git branch
|
||||
master *
|
||||
$ git branch -a
|
||||
master *
|
||||
remotes/origin/HEAD -> origin/master
|
||||
remotes/origin/experimental
|
||||
$ git branch --track experimental remotes/origin/experimental
|
||||
$ git branch
|
||||
master *
|
||||
experimental
|
||||
</code></div>
|
||||
|
||||
If you have many branches it can be useful to use the following *script*/*long command line*.
|
||||
|
||||
<div><code class="zsh">
|
||||
# first clone your project
|
||||
$ git clone git@github.com:yogsototh/project.git
|
||||
|
||||
# copy all branches
|
||||
$ zsh
|
||||
$ cd project
|
||||
$ for br in $( git br -a ); do
|
||||
case $br in
|
||||
remotes/*) print $br ;
|
||||
case ${br:t} in
|
||||
master|HEAD) continue ;;
|
||||
*) git branch --track ${br:t} $br ;;
|
||||
esac ;;
|
||||
esac
|
||||
done
|
||||
</code></div>
|
182
content/html/fr/blog/2010-03-23-Encapsulate-git.md
Normal file
182
content/html/fr/blog/2010-03-23-Encapsulate-git.md
Normal file
|
@ -0,0 +1,182 @@
|
|||
-----
|
||||
|
||||
# Custom
|
||||
isHidden: false
|
||||
menupriority: 1
|
||||
kind: article
|
||||
created_at: 2010-03-23T22:37:36+02:00
|
||||
title: Encapsulate git
|
||||
multiTitle:
|
||||
fr: Encapsuler git
|
||||
en: Encapsulate git
|
||||
multiDescription:
|
||||
fr: pas de description.
|
||||
en: no description.
|
||||
tags:
|
||||
- git
|
||||
- protection
|
||||
- branches
|
||||
- diverged
|
||||
|
||||
-----
|
||||
|
||||
<div class="small">
|
||||
Here is a solution to maintain divergent branches in git. Because it is easy to merge by mistake. I give a script that encapsulate git in order to forbid some merge and warn you some merge should be dangerous.
|
||||
</div>
|
||||
|
||||
## how to protect against your own dumb
|
||||
|
||||
I work on a project in which some of my git branches should remain divergent. And divergences should grow.
|
||||
|
||||
I also use some branch to contain what is common between projects.
|
||||
|
||||
Say I have some branches:
|
||||
|
||||
master: common to all branches
|
||||
dev: branch devoted to unstable development
|
||||
client: branch with features for all client but not general enough for master
|
||||
clientA: project adapted for client A
|
||||
clientB: project adapted for client B
|
||||
|
||||
Here how I want to work:
|
||||
|
||||
<%= blogimage("Dynamic branching","dynamic_branching.png") %>
|
||||
|
||||
And more precisely the branch hierarchy:
|
||||
|
||||
<%= blogimage("Branch hierarchy","branch_hierarchy.png") %>
|
||||
|
||||
An arrow from A to B means, you can merge A in B. If there is no arrow from A to B that means it is *forbidden* to merge A in B. Here is the corresponding rubycode:
|
||||
|
||||
<div><code class="ruby">
|
||||
$architecture={
|
||||
:master => [ :dev, :client ],
|
||||
:dev => [ :master ],
|
||||
:client => [ :clientA, :clientB ] }
|
||||
</code></div>
|
||||
|
||||
Having a `:master => [ :dev, :client ]` means you can merge `master` branch into `dev` and `client`.
|
||||
|
||||
If by mistake I make a `git checkout master && git merge clientA`, I made a mistake. This is why I made a script which encapsulate the git behaviour to dodge this kind of mistake.
|
||||
|
||||
But this script do far more than that. It also merge from top to down. The action `allmerges` will do:
|
||||
|
||||
<div><code class="zsh">
|
||||
git co dev && git merge master
|
||||
git co client && git merge master
|
||||
git co clientA && git merge client
|
||||
git co clientB && git merge client
|
||||
</code></div>
|
||||
|
||||
That means, I can update all branches. The algorithm will not make loop even if there is a cycle in the branch hierarchy.
|
||||
|
||||
Here it is:
|
||||
|
||||
<div class="small"><code class="ruby" file="eng">
|
||||
#!/usr/bin/env ruby
|
||||
# encoding: utf-8
|
||||
|
||||
# architecture
|
||||
#
|
||||
# master <-> dev
|
||||
# master -> client
|
||||
# clien -> clientA | clientB
|
||||
#
|
||||
# merge using two of these branches should be
|
||||
# restricted to these rules
|
||||
# merge to one of these branch and an unknown one should
|
||||
# raise a warning, and may the option to add this new branch
|
||||
# to the hierarchy
|
||||
|
||||
$architecture={
|
||||
:master => [ :dev, :client ],
|
||||
:dev => [ :master ],
|
||||
:client => [ :clientA, :clientB ] }
|
||||
|
||||
def get_current_branch()
|
||||
(`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
|
||||
end
|
||||
|
||||
if ARGV.length == 0
|
||||
puts %{usage: $0:t [git_command or local_command]
|
||||
|
||||
local commands:
|
||||
allmerges: merge from top to down}
|
||||
exit 0
|
||||
end
|
||||
|
||||
require 'set'
|
||||
$known_branches=Set.new
|
||||
$architecture.each do |k,v|
|
||||
$known_branches.add(k)
|
||||
v.each { |b| $known_branches.add(b) }
|
||||
end
|
||||
|
||||
def rec_merge(branch)
|
||||
if $architecture[branch].nil?
|
||||
return
|
||||
end
|
||||
$architecture[branch].each do |b|
|
||||
if $flag.has_key?(b.to_s + branch.to_s)
|
||||
next
|
||||
end
|
||||
flagname=branch.to_s + b.to_s
|
||||
if $flag.has_key?(flagname)
|
||||
next
|
||||
end
|
||||
if system %{eng checkout #{b}}
|
||||
if get_current_branch != b
|
||||
puts "Can't checkout to #{b}"
|
||||
exit 2
|
||||
end
|
||||
if system %{eng merge #{branch}}
|
||||
$flag[flagname]=true
|
||||
rec_merge(b)
|
||||
else
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def do_all_merges
|
||||
puts 'Will merge from father to sons'
|
||||
current_branch=get_current_branch
|
||||
$flag={}
|
||||
rec_merge(:master)
|
||||
system %{git co #{current_branch}}
|
||||
end
|
||||
|
||||
def do_merge
|
||||
current_branch=get_current_branch
|
||||
src_branch=ARGV[1].intern
|
||||
puts %{do_merge: #{src_branch} => #{current_branch}}
|
||||
if $known_branches.include?(current_branch)
|
||||
if $known_branches.include?(src_branch)
|
||||
if $architecture.has_key?(src_branch) and
|
||||
$architecture[src_branch].include?(current_branch)
|
||||
system %{git merge #{src_branch}}
|
||||
else
|
||||
puts %{Forbidden merge: #{src_branch} => #{current_branch}}
|
||||
end
|
||||
else
|
||||
puts %{Warning! #{src_branch} not mentionned in rb configuration}
|
||||
sleep 2
|
||||
f system %{git merge #{src_branch}}
|
||||
puts %{Warning! #{src_branch} not mentionned in rb configuration}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
case ARGV[0]
|
||||
when 'allmerges' then do_all_merges
|
||||
when 'merge' then do_merge
|
||||
else system %{git #{ARGV.join(' ')}}
|
||||
end
|
||||
</code></div>
|
||||
|
||||
All you need to do to make it work is simply to copy eng in a directory contained in your PATH.
|
||||
|
||||
Of course try to use as few as possible `cherry-pick` and `rebase`. This script was intended to work with workflow using `pull` and `merge`.
|
Loading…
Reference in a new issue