2013-10-07 49 views
1

我有一個在Mercurial存儲庫中的軟件。precommit mercurial鉤停止提交到錯誤的分支

我正在將我的軟件項目打包爲Debian軟件包。 看起來,執行此操作的標準方法是在Debian軟件包文件中有一個 獨立分支, 位於debian子目錄中。

我一直存在的一個問題是,我忘記了我是哪個分支 ,並且意外地犯下了錯誤的分支。這經常發生 ,真的很煩人。當發生這種情況時,我通常會在實現問題之前將 推送到遠程,然後讓 手動修復本地和遠程儲存庫,這是一種痛苦。

我能想到的唯一選擇是如果我嘗試對錯誤的分支進行提交,則會有一個預先提交鉤子 中止。

具體來說,我們假設主分支名爲default,並且包含Debian文件的分支 被稱爲debian。然後,我想要提交到default 分支才能成功,只要提交中的文件都不是來自debian 目錄。我只要提交debian目錄中的所有 文件都位於debian目錄中,就可以提交到debian目錄。

我花了一些時間閱讀有關Mercurial Hooks的章節,並通過Hg書中的示例 ,但仍然不知道如何去做這件事。我確實得到了強烈的印象 ,對於這樣的事情,我應該打電話給一個外部Python腳本,可能 在.hg/

回答

2

是的,你發現一個precommit掛鉤可以做到這一點。如果你想做到這一點在bash,那麼你可能會喜歡的東西去:

#!/bin/bash 
revs=$(hg log -r "$HG_NODE:tip" --template '{rev} ') #Intentional space after {rev} 
rc=0 
for rev in $revs 
do 
    files=$(hg log -r $rev --template '{files}') 
    #Above will include discards. So you cannot 'hg cat' them all. So you may want 
    # files=$(hg log -r $rev --template '{file_mods} {file_adds}') 
    branch=$(hg log -r $rev --template '{branch}') 
    for file in $files 
    do 
     if [ branch == "debian" ] && [ "$(echo $file | grep -v "debian")" != "" ] ; then 
      echo "ERROR: Non debian file in debian branch." 
      exit 1 
     fi 
     if [ branch != "debian" ] && [ "$(echo $file | grep "debian")" != "" ] ; then 
      echo "ERROR: debian file in non-debian branch." 
      exit 1 
     fi 
    done 
done 
exit $rc 

這些如果/ grep的行幾乎肯定是錯的,但你得到的圖片。

+0

謝謝Ry4an,這非常有幫助。使用shell而不是Python有什麼好處,反之亦然? –

+0

python在進程中運行,所以它會更有效率,但是您將學習一個新的非api來獲取提交中當前分支名稱和文件列表,而您可能已經知道如何在慶典。最後,可能更多的是關於您和您的團隊稍後將更容易定製的內容。一些例子可以在這裏找到:http://mercurial.selenic.com/wiki/HookExamples –

+0

嗨Ry4an。不知道你的意思是不是一個api。你的意思是Mercurial沒有固定的「官方」API? –

0

以@ Ry4an的解決方案爲出發點,我使用新的hglib API提出了以下腳本。

#!/usr/bin/python                                       

# Abort commit to the debian branch if it is not contained in a debian                          
# subdirectory                                        

# Similary abort commit to non-debian branches if it is contained in a                          
# debian subdirectory                                      

import hglib, os, sys 
client = hglib.open("/home/faheem/hooktest") 
ctx = client['tip'] 
files = ctx.files() 
branch = ctx.branch() 

for f in files: 
    d = os.path.dirname(f) 
    if branch == "debian" and d != "debian": 
     sys.exit("cannot commit %s (file not in 'debian' directory) to 'debian' branch"%f) 
    if branch != "debian" and d == "debian": 
     sys.exit("cannot commit %s (file in 'debian' directory) to non 'debian' branch"%f) 
0

使用進程內掛接的方法是以下代碼。這些 函數可用於像這樣的Mercurial存儲庫的.hgrc

pretxncommit.foo = python:mercurial_hooks.abort_commit_to_wrong_branch 
pre-qfinish.bar = python:mercurial_hooks.qfinish_abort_commit_to_wrong_branch 

abort_commit_to_wrong_branch不允許正常提交到錯誤 分支,但允許MQ提交。 qfinish_abort_commit_to_wrong_branch 會阻止qfinish將錯誤分支上的MQ提交轉換爲 定期提交。

我使用功能finishhttps://bitbucket.org/mirror/mercurial/src/tip/hgext/mq.py?at=default#cl-3034 作爲參考。

def abort_commit_to_wrong_branch(ui, repo, **kwargs): 
    """ 
    Don't allow commits to 'debian' branch including files not 
    contained in the 'debian/' directory. Also don't allow commits to 
    non-'debian' branches including files contained in the 'debian/' 
    directory. Don't restrict MQ commits. 
    """ 
    # If repo has '_committingpatch' attribute, then it is an mq 
    # commit in progress, so return 'False' 
    import os 
    ctx = repo[kwargs['node']] 
    files = ctx.files() 
    branch = ctx.branch() 
    if hasattr(repo, "_committingpatch"): 
     for f in files: 
      d = os.path.dirname(f) 
      if branch == "debian" and d != "debian": 
       ui.warn("Warning: committing %s (file not in 'debian' directory) to 'debian' branch. Allowed since this ia an MQ commit.\n"%f) 
      if branch != "debian" and d == "debian": 
       ui.warn("Warning: committing %s (file in 'debian' directory) to non 'debian' branch. Allowed since this ia an MQ commit.\n"%f) 
     return False 
    for f in files: 
     d = os.path.dirname(f) 
     if branch == "debian" and d != "debian": 
      ui.warn("Error: cannot commit %s (file not in 'debian' directory) to 'debian' branch\n"%f) 
      return True 
     if branch != "debian" and d == "debian": 
      ui.warn("Error: cannot commit %s (file in 'debian' directory) to non 'debian' branch\n"%f) 
      return True 

def qfinish_abort_commit_to_wrong_branch(ui, repo, **kwargs): 
    """ 
    Don't allow qfinish on 'debian' branch including files not 
    contained in the 'debian/' directory. Also don't allow qfinish on 
    non-'debian' branches including files contained in the 'debian/' 
    directory. Don't restrict MQ commits. 
    """ 
    from mercurial import scmutil 
    import os 
    if not repo.mq.applied: 
     ui.status(('no patches applied\n')) 
     return True 
    opts = kwargs['opts'] 
    # case corresponding to `-a`. no revisions specified. 
    if opts.get('applied'): 
     revrange = ('qbase::qtip',) 
    # case where revision(s) specified 
    revrange = kwargs['pats'] 
    revs = scmutil.revrange(repo, revrange) 
    # loop over revisions 
    for rev in revs: 
     ctx = repo[rev] 
     files = ctx.files() 
     branch = ctx.branch() 
     for f in files: 
      d = os.path.dirname(f) 
      if branch == "debian" and d != "debian": 
       ui.warn("Error: cannot commit %s (file not in 'debian' directory) to 'debian' branch\n"%f) 
       return True 
      if branch != "debian" and d == "debian": 
       ui.warn("Error: cannot commit %s (file in 'debian' directory) to non 'debian' branch\n"%f) 
       return True 
相關問題