2015-02-09 70 views
4

我正在遠程回購編寫git預接收鉤以確保推送的代碼符合我們公司的內部準則。在git預接收鉤子中訪問已更改的文件路徑

我能夠找到所有的文件,當一個預接收鉤被觸發時,但是,我沒有這些文件的路徑來打開它們使用正常的文件操作(例如cat git_working_directory/file_name會拋出No such file or directory錯誤)。 驗證代碼的應用程序需要文件路徑作爲參數,以便它可以打開文件並運行其檢查。

請考慮這種情況:開發人員創建一個新文件並將其推送到服務器,並觸發預接收掛鉤。在這個階段,新文件沒有保存到遠程的工作目錄,因爲預接收鉤仍在運行。

我想知道是否有一個臨時位置的文件保存在git中,只要他們被推送,以便我可以將該目錄傳遞給應用程序來運行檢查?

更新:

我能籤一個臨時位置並運行檢查存在,這可能是一種選擇,而是在考慮到開發人員經常推,有時甚至在同一時間和回購是非常大的,這個選項似乎不可行。我正在尋找更多的解決方案,我可以使用該文件的路徑,如果它以某種方式可用。

+0

遠程回購不應該有一個工作目錄。 – Holloway 2015-02-09 16:39:28

+0

您需要將文件檢入臨時工作目錄並在那裏運行檢查。 – larsks 2015-02-09 16:39:46

+0

@larsks是否有一個git命令,我可以運行這些文件來檢查臨時目錄? – aBadAssCowboy 2015-02-09 16:42:34

回答

0

您可能需要編寫pre-receive掛鉤來檢出臨時位置中的文件。通常,這意味着你將git clone裸倉庫放到一個臨時目錄中,然後檢查出具體的提交併運行你的檢查。例如,像:

#!/bin/sh 

REPO=$PWD 

check_files_in() { 
    rev=$1 

    # create a temporary working directory 
    workdir=$(mktemp -d gitXXXXXX) 
    (
    # arrange to clean up the workding directory 
    # when the subshell exits 
    trap "cd /; rm -rf $workdir" EXIT 

    # unset GIT_DIR because it would confuse things 
    unset GIT_DIR 

    # clone the repository 
    cd $workdir 
    git clone $REPO check 

    # checkout the specific revision we're checking 
    cd check 
    git checkout $rev 

    # perform some sort of validation. The exit code of this 
    # command will be the exit code of this function, so 
    # returning an error will reject the push. 
    run-validation-scripts 
) 
} 

while read oldrev newrev refname; do 
    check_files_in $newrev || exit 1 
done 
+0

考慮到開發人員將代碼非常頻繁地推送到服務器上,有時甚至是在同一時間,這會是最佳嗎?我更喜歡尋找一個文件已被git保存的位置,我可以訪問它。 – aBadAssCowboy 2015-02-16 08:56:47

4

我不知道是否存在其中的文件,儘快爲他們被推保存在git的,這樣我可以通過該目錄運行應用程序的一個臨時位置檢查?

不,沒有這樣的地方。這些文件存儲爲blob,可以減少爲增量和/或壓縮,因此不能保證它們在「準備使用」狀態的任何地方都可用。

檢查標準的應用程序需要文件路徑作爲參數,以便它可以打開文件並運行其檢查。

如果你在linux上,你可以指向/dev/stdin作爲輸入文件,並通過管道放置文件。

#!/bin/sh 
while read oldrev newrev refname; do 
git diff --name-only $oldrev $newrev | while read file; do 
    git show $newrev:$file | validate /dev/stdin || exit 1 
    done 
done 
+0

看起來像一個可行的選擇,我會盡力讓你知道。 – aBadAssCowboy 2015-02-16 08:52:12

+0

現在我想到了它,我意識到這需要一個工作副本(它不應該出現在服務器上)。我會在一分鐘內更新我的答案,直接從回購中提取 – joozek 2015-02-16 09:22:09

+0

@SriVishnuTotakura我編輯了我的回答,刪除了WC的存在要求。看看它 – joozek 2015-02-16 09:33:30

0

推送的文件保存在永久位置,即作爲存儲庫中的git對象。提取它們的一種方法是使用git archive

#! /usr/bin/perl -T 

use strict; 
use warnings; 

# replace with your real check program and optional arguments 
my @CHECK_PROGRAM = qw/ ls -la /; 
#my @CHECK_PROGRAM = qw/ false /; 

use File::Temp qw/ tempdir /; 

$ENV{PATH} = "/bin:/usr/bin"; 

while (<>) { 
    # <old-value> SP <new-value> SP <ref-name> LF 
    my($oldsha,$newsha,$refname) = /\A([^ ]+) ([^ ]+) ([^ ]+)\x0A\z/; 
    die "$0: unexpected input: $_" unless defined $refname; 

    my $tmp = tempdir "prerecv-$$-XXXXXX", DIR => "/tmp", CLEANUP => 1; 

    system(qq{git archive --format=tar $newsha | tar -C "$tmp" -x}) == 0 
    or die "$0: git-archive $newsha failed"; 

    system(@CHECK_PROGRAM, $tmp) == 0 or die "$0: check failed"; 
} 

因爲代碼代表其他用戶身份運行,它能夠與-T開關Perl的taint mode安全功能。

請注意,您的檢查程序會在不知道哪些文件已更改的情況下看到整個樹被推送。如果檢查器也需要關於三角洲的信息,請調查git diff-tree及其可能的--diff-filter選項。

+0

不是'git archive'類似於複製文件?考慮到開發人員非常頻繁地將代碼推送到服務器上,有時甚至是同時推送代碼,這會是最佳嗎?我正在尋找一個他們已經被git保存並且我可以訪問的位置。 – aBadAssCowboy 2015-02-16 08:55:16

+0

@SriVishnuTotakura您不能指望任何這樣的目錄位置與遠程存儲庫相關聯,因此上面的掛鉤將與提交關聯的目錄樹的狀態複製到臨時位置,以便您的檢查器或驗證應用程序可以完成其工作。 Git更新是原子的,所以鉤子不必擔心併發推送。如果被跟蹤的目錄樹很大,比如說1+ GiB,你可能會擔心,但即使如此,我還是建議重新組織你的存儲庫結構。 – 2015-02-16 14:18:07