2016-09-10 4 views
4

파이썬 코드와 자식은 diff를 구문 분석하고 싶습니다 내가 사랑하는 파서에서 다음과 같은 정보를 얻을 관심 :파이썬 힘내 사랑하는 파서

  1. 삭제/추가 라인의 내용도 행 번호를.
  2. 파일 이름.
  3. 파일의 삭제, 이름 변경 또는 추가 여부를 나타냅니다.

나는이 목적을 위해 unidiff 0.5.2를 사용하고 난 다음 코드를 작성 : 나는 힘내은 diff를 생성하는 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 문자열을 파싱하는 것이 무슨 뜻입니까?" 훨씬 더 나은 것은 "나는이 자식 자식 문자열을 가지고 있는데, 다음 정보를 얻고 싶습니다. 여기 제가 시도한 것이 있습니다. 왜 여기가 작동하지 않는 것입니까?" – mgilson

+0

고맙습니다. 귀하의 의견. 나는 그 질문을 다시 쓸 것이다. –

+0

당신은 당신이'unidiff '를 사용할 수 없다고 말합니다 - 나는 그 주장을 이해하고 있는지 확신 할 수 없습니다. 연결된 pypi 페이지에 따르면 unidiff는 파일과 유사한 객체로 작동합니다. 문자열이 있으면 표준 라이브러리에서'StringIO' 또는'io'를 사용하여 파일과 비슷한 객체를 생성하기 쉽습니다. – mgilson

답변

1

마지막으로 해결책을 찾았습니다. gitpython의 출력은 표준 git diff 출력과 조금 다릅니다. 표준 자식 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 시작을 생성합니다. 하지만 이름 바꾸기 파일 (diff_filter = 'cr')의 git diff를 필터링했기 때문에 오류가 발생하지 않습니다.

+0

아마도 diff_index [i] .diff를 사용할 수 있는데, 이는'@@ '보다 먼저 제거합니다. – tdihp