jgit

2011-01-24 12 views
8

के साथ एक फ़ाइल के लिए लूपिंग पर लूपिंग, मैं एक रिपोज़ को जोड़ने और जोड़ने, कम करने और फ़ाइलों के लिए प्रतिबद्ध संदेशों को लूप करने के मामले में jGit फ़ाइल की मूल बातें के साथ पकड़ने में कामयाब रहा हूं।jgit

File gitDir = new File("/Users/myname/Sites/helloworld/.git"); 

RepositoryBuilder builder = new RepositoryBuilder(); 
Repository repository; 
repository = builder.setGitDir(gitDir).readEnvironment() 
     .findGitDir().build(); 

Git git = new Git(repository); 
RevWalk walk = new RevWalk(repository); 
RevCommit commit = null; 

// Add all files 
// AddCommand add = git.add(); 
// add.addFilepattern(".").call(); 

// Commit them 
// CommitCommand commit = git.commit(); 
// commit.setMessage("Commiting from java").call(); 

Iterable<RevCommit> logs = git.log().call(); 
Iterator<RevCommit> i = logs.iterator(); 

while (i.hasNext()) { 
    commit = walk.parseCommit(i.next()); 
    System.out.println(commit.getFullMessage()); 

} 

क्या मैं आगे क्या करना चाहते हैं एक एकल फाइल के लिए सभी प्रतिबद्ध संदेश मिलता है और फिर वापस समय में एक विशिष्ट संदर्भ/बात करने के लिए एकल फाइल वापस लौटने में सक्षम हो करने में सक्षम हो सकता है।

उत्तर

9

यहाँ के सभी माता-पिता पर एक आधार के लिए प्रतिबद्ध परिवर्तन करता है खोजने के लिए कैसे है

 var tree = new TreeWalk(repository) 
     tree.addTree(commit.getTree) 
     commit.getParents foreach { 
      parent => tree.addTree(parent.getTree) 
     } 
     tree.setFilter(TreeFilter.ANY_DIFF) 

(स्केला कोड)

ध्यान दें कि TreeFilter.ANY_DIFF एक भी पेड़ के लिए काम करता वॉकर और इच्छा मूल प्रतिबद्धता में उपलब्ध सभी तत्वों को वापस करें।

आपको तब पेड़ पर फिर से चलना होगा ताकि यह देखने के लिए कि आपकी फ़ाइल दी गई डेल्टा में है (यह काफी आसान है)।

while (tree.next) 
      if (tree.getDepth == cleanPath.size) { 
       // we are at the right level, do what you want 
      } else { 
       if (tree.isSubtree && 
        name == cleanPath(tree.getDepth)) { 
        tree.enterSubtree 
       } 
      } 
    } 

अब एक RevWalk.next लूप में है कि कोड लपेट और आप प्रतिबद्ध और फ़ाइलों के लिए प्रतिबद्ध द्वारा बदल मिलेगा (cleanPath रेपो रास्ते में शुद्ध, '/' के आधार पर विभाजित है)।

आप ANY_DIFF की तुलना में एक अलग फ़िल्टर का उपयोग करना चाह सकते हैं, क्योंकि एक पेड़ अलग होने पर ANY_DIFF सत्य है। यह एक विलय के मामले में थोड़ा सा अंतर्ज्ञानी है जहां सभी मूल पेड़ की तुलना में ब्लॉब नहीं बदला था। तो यहाँ एक ALL_DIFF के मूल है कि केवल तत्व है कि सभी माता पिता के पेड़ से अलग दिखाई देगा, यह है: (, स्केला कोड AnyDiffFilter से ली गई)

override def include(walker: TreeWalk): Boolean = { 
    val n = walker.getTreeCount(); 
    if (n == 1) { 
     return true; 
    } 
    val m = walker.getRawMode(0) 
    var i = 1 
    while (i < n) { 
     if (walker.getRawMode(i) == m && walker.idEqual(i, 0)) { 
      return false 
     } 
     i += 1 
    } 
    true 
} 

+0

धन्यवाद, यह वास्तव में मेरी मदद करता है। +1 – Dylan

2

किसी विशिष्ट फ़ाइल के इतिहास को खोजने के लिए गिट के साथ सामान्य दृष्टिकोण संशोधन ग्राफ (जो आप कर रहे हैं) के माध्यम से चलना है और प्रत्येक के लिए, प्रश्न में पथ द्वारा संदर्भित वस्तु का परीक्षण करें (या तो एक हो सकता है ब्लॉब या एक पेड़ एक पूरे उप-विषय के लिए इतिहास खोजने के लिए)। तो अनिवार्य रूप से संशोधन वॉकर द्वारा संशोधन सेट आउटपुट पर फ़िल्टर के रूप में कार्य करें।

jgit दस्तावेज लगता है ... स्पैस। लेकिन आपको प्रत्येक RevCommit के अनुरूप एक RevTree प्राप्त करने में सक्षम होना चाहिए, और यदि आवश्यक हो तो प्रत्येक पथ खंड के साथ टर्मिनल ऑब्जेक्ट आईडी पर जाएं।

1

araqnid सही है, यह है कि मैं कितना तिथियां की एक सूची है, प्रतिबद्ध करने के लिए है कि प्रश्न में फ़ाइल शामिल संबंधित प्रत्येक तिथि ...

तो फिर तुम एक विशिष्ट से पुनर्प्राप्त कर सकते हैं प्रतिबद्ध आप के रूप में फ़ाइल का नाम और प्रतिबद्धता की तारीख, नीचे दी गई दो विधियों को देखें ....

नोट: यह कोड एक .groovy वर्ग में है, इसलिए आपको जावा के लिए थोड़ा सा संशोधन करना होगा।

byte[] getAnyPreviousVersionFileBytes(String relativeFilePath, Date date) { 

    byte[] bytes = null 
    try { 

     RevWalk revWalk = new RevWalk(repository) 
     ObjectId headId = repository.resolve(Constants.HEAD); 
     RevCommit root = revWalk.parseCommit(headId); 

     revWalk.sort(RevSort.COMMIT_TIME_DESC); 
     revWalk.markStart(root); 

     for (RevCommit revCommit: revWalk) { 

      // if date matches then walk the tree in this commit 
      if (new Date(revCommit.commitTime * 1000L) == date) { 

       TreeWalk treeWalk = TreeWalk.forPath(repository, relativeFilePath, revCommit.getTree()) 

       if (treeWalk != null) { 
        treeWalk.setRecursive(true) 
        CanonicalTreeParser canonicalTreeParser = treeWalk.getTree(0, CanonicalTreeParser) 

        while (!canonicalTreeParser.eof()) { 

         // if the filename matches, we have a match, so set teh byte array to return 
         if (canonicalTreeParser.getEntryPathString() == relativeFilePath) { 
          ObjectLoader objectLoader = repository.open(canonicalTreeParser.getEntryObjectId()) 
          bytes = objectLoader.bytes 
         } 
         canonicalTreeParser.next(1) 
        } 
       } 
      } 

     } 

    } 
    catch (Exception e) { 
     throw new JgitException(e) 
    } 
    return bytes 
} 

List<Date> getFileVersionDateList(String relativeFilePath) { 

    List<Date> versions = new LinkedList<Date>() 
    try { 

     RevWalk revWalk = new RevWalk(repository) 
     ObjectId headId = repository.resolve(Constants.HEAD); 
     RevCommit root = revWalk.parseCommit(headId); 

     revWalk.sort(RevSort.COMMIT_TIME_DESC); 
     revWalk.markStart(root); 

     for (RevCommit revCommit: revWalk) { 

      TreeWalk treeWalk = TreeWalk.forPath(repository, relativeFilePath, revCommit.getTree()) 

      if (treeWalk != null) { 
       treeWalk.setRecursive(true) 
       CanonicalTreeParser canonicalTreeParser = treeWalk.getTree(0, CanonicalTreeParser) 

       while (!canonicalTreeParser.eof()) { 
        // if the filename matches, we have a match, so add the date of this commit to the list 
        if (canonicalTreeParser.getEntryPathString() == relativeFilePath) { 
         versions.add(new Date(revCommit.commitTime * 1000L)) 
        } 
        canonicalTreeParser.next(1) 
       } 
      } 
     } 
    } 
    catch (Exception e) { 
     throw new JgitException(e) 
    } 

    return versions 
} 
6

तो मैं charlieboy के समाधान काम करने के लिए प्राप्त करने की कोशिश, और यह ज्यादातर किया, लेकिन यह मेरे लिए निम्नलिखित मामले में विफल रहा (शायद उस पोस्ट के बाद से jgit में कुछ बदल गया?)

ऐड fileA, प्रतिबद्ध "प्रतिबद्ध 1" के रूप में , fileB जोड़ने के लिए प्रतिबद्ध के रूप में "2 के लिए प्रतिबद्ध"

getFileVersionDateList("fileA") 

दोनों commit 1 और commit 2, पाए गए जहाँ मैं उम्मीद केवल commit 1

मेरे समाधान इस प्रकार थी:

List<Commit> commits = new ArrayList<Commit>(); 

RevWalk revWalk = new RevWalk(repository); 
revWalk.setTreeFilter(
     AndTreeFilter.create(
       PathFilterGroup.createFromStrings(<relative path in question>), 
       TreeFilter.ANY_DIFF) 
); 

RevCommit rootCommit = revWalk.parseCommit(repository.resolve(Constants.HEAD)); 
revWalk.sort(RevSort.COMMIT_TIME_DESC); 
revWalk.markStart(rootCommit); 

for (RevCommit revCommit : revWalk) { 
    commits.add(new GitCommit(getRepository(), revCommit)); 
} 

LogCommand का उपयोग करना भी सरल है, और इस तरह दिखता है:

List<Commit> commitsList = new ArrayList<Commit>(); 

Git git = new Git(repository); 
LogCommand logCommand = git.log() 
     .add(git.getRepository().resolve(Constants.HEAD)) 
     .addPath(<relative path in question>); 

for (RevCommit revCommit : logCommand.call()) { 
    commitsList.add(new GitCommit(this, revCommit)); 
} 

जाहिर है आप भी प्रतिबद्ध तारीख,, आवश्यकतानुसार जाँच चाहते हैं आदि ।

+0

यह समाधान मेरे लिए वास्तविक उत्तर से बेहतर है। – webmaster

+0

वास्तव में महान और साफ कोड, बहुत मदद की, kudos – Olix

संबंधित मुद्दे