Git
Chapters ▾ 2nd Edition

A2.3 Ek bölüm B: Git’i Uygulamalarınıza Gömmek - JGit

JGit

Git’i bir Java programından kullanmak istiyorsanız, JGIT adlı tam özellikli bir GIT kütüphanesi bulunmaktadır. JGIT Java’da yerel olarak yazılmış, GIT’in nispeten tam özellikli bir uygulamasıdır ve Java topluluğunda yaygın olarak kullanılmaktadır. JGIT projesi Eclipse şemsiyesi altındadır https://www.eclipse.org/jgit/ adresinde bulunabilir.

Kurulum

Projenizi JGit’e bağlamanın ve kod yazmaya başlamanın çeşitli yolları vardır. Muhtemelen en kolayı Maven’i kullanmaktır; aşağıdaki kod parçacığını pom.xml dosyanızdaki <dependencies>` (bağımlılıklar) etiketine ekleyerek entegrasyonu gerçekleştirebilirsiniz:

<dependency>
    <groupId>org.eclipse.jgit</groupId>
    <artifactId>org.eclipse.jgit</artifactId>
    <version>3.5.0.201409260305-r</version>
</dependency>

Siz bunu okuduğunuzda sürüm büyük olasılıkla ilerlemiş olacaktır; Güncellenmiş repo bilgileri için https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit adresini kontrol edin. Bu adım tamamlandığında Maven, ihtiyaç duyacağınız JGit kitaplıklarını otomatik olarak alacak ve kullanacaktır.

İkilik bağımlılıkları kendiniz yönetmeyi tercih ederseniz, önceden oluşturulmuş JGit ikilik dosyalarına https://www.eclipse.org/jgit/download adresinden ulaşabilirsiniz. Aşağıdaki gibi bir komut çalıştırarak bunları projenize dahil edebilirsiniz:

javac -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App.java
java -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App

Tesisat (Plumbing)

JGit’in iki temel API seviyesi vardır: tesisat ve döşeme. Bunların terminolojisi Git’in kendisinden gelir ve JGit aşağı yukarı aynı türden alanlara bölünmüştür: döşeme API’leri, ortak kullanıcı düzeyindeki eylemler (normal bir kullanıcının Git komut satırını kullanacağı türden şeyler) için kullanıcı dostu bir ön yüzdür, tesisat API’leri ise düşük seviyeli repo nesneleriyle doğrudan etkileşim kurmak içindir.

Çoğu JGit oturumunun başlangıç ​​noktası Repository sınıfıdır ve yapmak isteyeceğiniz ilk şey onun bir örneğini oluşturmaktır. Dosya sistemi tabanlı bir repo için (evet, JGit diğer depolama modellerine izin verir), bu FileRepositoryBuilder kullanılarak gerçekleştirilir:

// Create a new repository
Repository newlyCreatedRepo = FileRepositoryBuilder.create(
    new File("/tmp/new_repo/.git"));
newlyCreatedRepo.create();

// Open an existing repository
Repository existingRepo = new FileRepositoryBuilder()
    .setGitDir(new File("my_repo/.git"))
    .build();

Oluşturucu, programınızın tam olarak nerede bulunduğunu bilse de bilmese de, bir Git reposu bulmak için ihtiyaç duyduğu her şeyi sağlayan akıcı bir API’ye sahiptir. Ortam değişkenlerini (.readEnvironment()) kullanabilir, çalışma dizinindeki bir yerden başlayıp, arama yapabilir (.setWorkTree(…).findGitDir()) veya yukarıdaki gibi bilinen bir .git dizinini açabilir.

Bir Repository örneğine sahip olduğunuzda, onunla her türlü şeyi yapabilirsiniz. İşte hızlı bir örnekleme:

// Get a reference
Ref master = repo.getRef("master");

// Get the object the reference points to
ObjectId masterTip = master.getObjectId();

// Rev-parse
ObjectId obj = repo.resolve("HEAD^{tree}");

// Load raw object contents
ObjectLoader loader = repo.open(masterTip);
loader.copyTo(System.out);

// Create a branch
RefUpdate createBranch1 = repo.updateRef("refs/heads/branch1");
createBranch1.setNewObjectId(masterTip);
createBranch1.update();

// Delete a branch
RefUpdate deleteBranch1 = repo.updateRef("refs/heads/branch1");
deleteBranch1.setForceUpdate(true);
deleteBranch1.delete();

// Config
Config cfg = repo.getConfig();
String name = cfg.getString("user", null, "name");

Burada pek çok şey gerçekleştiği için her seferinde bir bölüm üzerinden geçelim.

İlk satır master referansa bir işaretçi alır. JGit refs/heads/master konumunda bulunan gerçek master referansını otomatik olarak alır ve referans hakkında bilgi almanıza olanak tanıyan bir nesne döndürür. Adı (.getName()) ve doğrudan referansın hedef nesnesini (.getObjectId()) ya da sembolik bir referansla gösterilen referansı (.getTarget()) alabilirsiniz. Ref nesneleri ayrıca etiket referanslarını ve nesnelerini temsil etmek için de kullanılır; bu nedenle, etiketin (potansiyel olarak uzun) bir etiket nesneleri dizisinin son hedefini işaret ettiği anlamına gelen peeled (soyulmuş) olup olmadığını sorabilirsiniz.

İkinci satır, ObjectId örneği olarak döndürülen master referansının hedefini alır. ObjectId Git’in nesne veritabanında bulunabilen veya bulunmayan bir nesnenin SHA-1 karmasını temsil eder. Üçüncü satır benzerdir ancak JGit’in ters ayrıştırma sözdizimini nasıl işlediğini gösterir (bununla ilgili daha fazla bilgi için bkz. Dal Referansları). Git’in anladığı herhangi bir nesne belirtecini iletebilirsiniz ve JGit o nesne için geçerli bir ObjectId veya null döndürecektir.

Sonraki iki satır, bir nesnenin ham içeriğinin nasıl yükleneceğini gösterir. Bu örnekte, nesnenin içeriğini doğrudan stdout’a aktarmak için ObjectLoader.copyTo()'yu çağırıyoruz, ancak ObjectLoader'ın ayrıca bir nesnenin türünü ve boyutunu okumak ve onu bir bayt dizisi olarak döndürmek için de yöntemleri vardır. Büyük nesneler için (burada `.isLarge(), true değerini döndürür), ham nesne verilerini hepsini aynı anda belleğe çekmeden okuyabilen OutputStream benzeri bir nesne elde etmek için .openStream() çağrısını yapabilirsiniz.

Sonraki birkaç satır yeni bir dal oluşturmak için ne gerektiğini gösteriyor. Bir RefUpdate örneği oluşturuyoruz, bazı parametreleri yapılandırıyoruz ve değişikliği tetiklemek için .update() çağrısını yapıyoruz. Doğrudan bunu takip eden kod aynı dalı silmek için kullanılır. Bunun çalışması için .setForceUpdate(true)`nin gerekli olduğunu unutmayın; aksi takdirde `.delete() çağrısı REJECTED sonucunu döndürecek ve hiçbir şey olmayacaktır.

Son örnek, Git yapılandırma dosyalarından user.name değerinin nasıl alınacağını gösterir. Bu Config örneği, yerel yapılandırma için daha önce açtığımız repoyu kullanır, ancak genel ve sistem yapılandırma dosyalarını otomatik olarak algılayacak ve onlardan değerleri okuyacaktır.

Bu, tam tesisat API’sinin yalnızca küçük bir örneğidir (daha birçok yöntem ve sınıf mevcuttur). Ayrıca burada JGit’in istisnaları kullanarak hataları nasıl ele aldığı gösterilmemiştir. JGit API’leri bazen standart Java istisnaları (IOException gibi) atar, ancak aynı zamanda JGit’e özgü sağlanan bir dizi istisna türü de vardır (NoRemoteRepositoryException, CorruptObjectException, ve NoMergeBaseException gibi).

Döşeme (Porcelain)

Tesisat API’leri oldukça eksiksizdir ancak dizine bir dosya eklemek veya yeni bir katkıda bulunmak gibi ortak hedeflere ulaşmak için bunları bir araya getirmek zahmetli olabilir. JGit bu konuda yardımcı olmak için daha üst düzeyde bir API seti sağlar ve bu API’lerin giriş noktası Git sınıfıdır:

Repository repo;
// construct repo...
Git git = new Git(repo);

Git sınıfı, oldukça karmaşık bazı davranışlar oluşturmak için kullanılabilecek builder tarzı, bir dizi üst düzey yönteme sahiptir. git ls-remote gibi bir şey yaparak şu örneğe bakalım:

CredentialsProvider cp = new UsernamePasswordCredentialsProvider("username", "p4ssw0rd");
Collection<Ref> remoteRefs = git.lsRemote()
    .setCredentialsProvider(cp)
    .setRemote("origin")
    .setTags(true)
    .setHeads(false)
    .call();
for (Ref ref : remoteRefs) {
    System.out.println(ref.getName() + " -> " + ref.getObjectId().name());
}

Bu Git sınıfında ortak bir kalıptır; metodlar, parametreleri ayarlamak için metod çağrılarını zincirlemenize izin veren bir komut nesnesi döndürür. Bunlar .call() çağrısı yaptığınızda yürütülür. Bu durumda, origin uzaktan reposundan etiketler istiyoruz, ancak uçları (HEAD) istemiyoruz. Ayrıca kimlik doğrulama için CredentialsProvider nesnesinin kullanıldığına da dikkat edin.

Git sınıfı aracılığıyla; add, blame, commit, clean, push, rebase, revert, reset ve daha birçok başka komut mevcuttur.

İleri Okumalar

Bu JGit’in tüm parçalarının sadece küçük bir örneklemesidir. Eğer daha fazla bilgi edinmek istiyorsanız, daha fazla bilgi ve ilham alabileceğiniz yerleri burada bulabilirsiniz:

scroll-to-top