2016-09-10 13 views
4

私はPythonのコードをGitの差分を解析したいと私は差分パーサから以下の情報を得るために興味があります:削除のPythonのGitの差分パーサ

  1. コンテンツ/ラインとも行番号を追加しました。
  2. ファイル名。
  3. ファイルの削除、名前変更、追加のステータス。

私は、この目的のためにunidiff 0.5.2を使用していると私は、次のコードを書きました:私はGitの差分を生成するGitPythonを使用しています

from unidiff import PatchSet 
    import git 
    import os 

    commit_sha1 = 'b4defafcb26ab86843bbe3464a4cf54cdc978696' 
    repo_directory_address = '/my/git/repo' 
    repository = git.Repo(repo_directory_address) 
    commit = repository.commit(commit_sha1) 
    diff_index = commit.diff(commit_sha1+'~1', create_patch=True) 
    diff_text = reduce(lambda x, y: str(x)+os.linesep+str(y), diff_index).split(os.linesep) 
    patch = PatchSet(diff_text) 
    print patch[0].is_added_file 

。上記のコードに次のエラーが表示されました。

current_file = PatchedFile(source_file, target_file, 
    UnboundLocalError: local variable 'source_file' referenced before assignment 

このエラーを修正するお手伝いをしていただければ幸いです。

+0

この質問にはいくつか問題があります。まず、図書館やその他のオフサイトのリソースを推薦するように求めています。第二に、あなたの要求が何であるか教えてくれませんでした。「git diff文字列を解析する」とはどういう意味ですか? 「このgit diff文字列を持っていて、次の情報を取得したいと思っています。ここに私が試したことがあります。ここにはなぜうまくいかないのですか...」 – mgilson

+0

ありがとうあなたのコメント。私は質問を書き直します。 –

+0

あなたは 'unidiff'を使うことはできないと言います - 私はその主張を理解しているかどうかはわかりません。あなたがリンクしたピピページによると、unidiffはファイルのようなオブジェクトで動作します。文字列があれば、標準ライブラリで 'StringIO'や' io'を使ってファイルのようなオブジェクトを作るのは簡単です。 – mgilson

答えて

1

最後に、解決策が見つかりました。 gitpythonの出力は標準のgit diff出力と少し異なります。標準のgit diffソースファイルでは、---で始まりますが、gitpythonの出力は、------で始まります。次のpythonコードを実行して出力します(この例はelasticsearch repositoryで生成されています)。 ):

import git 

repo_directory_address = '/your/elasticsearch/repository/address' 
revision = "ace83d9d2a97cfe8a8aa9bdd7b46ce71713fb494" 
repository = git.Repo(repo_directory_address) 
commit = repository.commit(rev=revision) 
# Git ignore white space at the end of line, empty lines, 
# renamed files and also copied files 
diff_index = commit.diff(revision+'~1', create_patch=True, ignore_blank_lines=True, 
         ignore_space_at_eol=True, diff_filter='cr') 

print reduce(lambda x, y: str(x)+str(y), diff_index) 

アウトプット部分は以下のようになります:

core/src/main/java/org/elasticsearch/action/index/IndexRequest.java 
======================================================= 
lhs: 100644 | f8b0ce6c13fd819a02b1df612adc929674749220 
rhs: 100644 | b792241b56ce548e7dd12ac46068b0bcf4649195 
------ a/core/src/main/java/org/elasticsearch/action/index/IndexRequest.java 
+++ b/core/src/main/java/org/elasticsearch/action/index/IndexRequest.java 
@@ -20,16 +20,18 @@ 
package org.elasticsearch.action.index; 

import org.elasticsearch.ElasticsearchGenerationException; 
+import org.elasticsearch.Version; 
import org.elasticsearch.action.ActionRequestValidationException; 
import org.elasticsearch.action.DocumentRequest; 
import org.elasticsearch.action.RoutingMissingException; 
import org.elasticsearch.action.TimestampParsingException; 
import org.elasticsearch.action.support.replication.ReplicationRequest; 
import org.elasticsearch.client.Requests; 
+import org.elasticsearch.cluster.metadata.IndexMetaData; 
import org.elasticsearch.cluster.metadata.MappingMetaData; 
import org.elasticsearch.cluster.metadata.MetaData; 
import org.elasticsearch.common.Nullable; 
-import org.elasticsearch.common.UUIDs; 
+import org.elasticsearch.common.Strings; 
import org.elasticsearch.common.bytes.BytesArray; 
import org.elasticsearch.common.bytes.BytesReference; 

ソースファイルの4行目は、------で始める見ることができるように。ソースファイルが名前を変更した場合:

RE_SOURCE_FILENAME = re.compile(
         r'^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?') 

へ:

RE_SOURCE_FILENAME = re.compile(
        r'^------ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?') 

PS問題を解決するには、あなたがから/unidiff/constants.pyで見つけるunidiff 0.5.2のソース・ファイル内の正規表現を編集する必要があります、gitpythonは---で差分開始を生成します。しかし、リネームファイル(diff_filter = 'cr')のgit diffをフィルタリングしたので、エラーは発生しません。

+0

たぶん、diff_index [i] .diffを使うことができます。これは '@@'の前にあるものを取り除きます。 – tdihp