[JAVA] Faire une capture incomplète de l'étape / unstage du client GUI hebdomadaire [2]

Ceci est une continuation de Créer un client GUI hebdomadaire [1] stage / unstage connaissances de base.

Je ne parle pas encore de GUI

C'est la trajectoire entre le début de l'utilisation de JGit et l'abandon. Il peut également être lu comme une introduction à JGit. Je n'ai pas encore parlé de l'interface graphique.

libgit2 et liaisons linguistiques

Il existe une bibliothèque C appelée libgit2. Si c'est un langage qui peut coopérer avec C (?) Vous pouvez l'utiliser pour créer des applications et des bibliothèques git. https://github.com/libgit2/libgit2#language-bindings Si vous avez une belle bibliothèque dans la langue que vous souhaitez utiliser Vous pouvez l'utiliser dans votre propre application ou intégrer libgit en y faisant référence. [A2.2 Annexe B: Incorporer Git dans votre application - Comment utiliser Libgit2](https://git-scm.com/book/ja/v2/Appendix-B:-Git%E3%82%92% E3% 81% 82% E3% 81% AA% E3% 81% 9F% E3% 81% AE% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 82% B1% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E3% 81% AB% E7% B5% 84% E3% 81% BF% E8% BE% BC% E3% 82% 80-Libgit2% E3% 82% 92% E4% BD% BF% E3% 81% 86% E6% 96% B9% E6% B3% 95)

Ne combattez pas l'environnement

Par exemple, je suis un développeur d'applications iOS / Android Cela ressemble à un peu de JavaScript et de TypeScript dans une application hybride. Je voulais écrire un TypeScript, alors j'ai essayé nodegit, mais J'ai abandonné parce que je ne pouvais pas le déplacer avec Electron dans mon environnement. [Git-utils] d'Atom (https://github.com/atom/git-utils) ne fonctionne pas non plus avec Electron.

Alors, utilisons Java. Puisqu'il s'agit d'un Androider, il semble que vous puissiez être impressionné simplement en disant Java 8.

Les liaisons de langue ci-dessus ont dentelées,

This is very experimental, very mediocre JNI bindings for libgit2.

Je ne suis pas habitué à JNI, j'ai donc décidé d'utiliser tranquillement JGit ici.

JGit

De la conclusion, il n'y en a pas assez. De plus, cela semble être une implémentation originale plutôt qu'une liaison à libgit2, et elle se comporte différemment de la commande git.

Non limité à JGit, les bibliothèques de chaque langage peuvent ne pas avoir toutes les fonctions git nécessaires, Je pense que ça ira jusqu'à ce que vous créiez un framework GUI tel que "Acquérir et afficher Diff".

La version utilisée était 4.8.0.201706111038-r.

build.gradle


dependencies {
    // https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit
    compile group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '4.8.0.201706111038-r'
}

diff

Sortie sous forme de texte

Pour obtenir le diff sous forme de texte: Passer à FileRepositoryBuilder.create () n'est pas le haut du référentiel, mais le répertoire .git.

        final File gitDir; // .répertoire git
        final Repository repository = FileRepositoryBuilder.create(gitDir)
        final Git git = new Git(repository);
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final List<DiffEntry> entryList = git.diff()
                .setCached(cached)
                .setOutputStream(bos)
                .call();
        final String text = new String(bos.toByteArray(), StandardCharsets.UTF_8)

Diverses options pour DiffCommand renvoyées par git.diff () Pour appeler call ().

Idem pour les autres commandes

Les commandes autres que diff ont une interface similaire.

  1. Obtenez une instance de la classe qui correspond à la commande git
  2. Définissez les options
  3. Obtenez le résultat avec la méthode call ()

DiffFormatter

[DiffEntry] avec git.diff (). Call () (http://download.eclipse.org/jgit/site/4.8.0.201706111038-r/apidocs/org/eclipse/jgit/diff/DiffEntry.html) Vous pouvez également le récupérer puis le recracher sur OutputStream. Utilisez la classe DiffFormatter. (Même si OutputStream est défini dans DiffCommand, DiffFormatter est utilisé dans la méthode call ().)

Il y a quelques mises en garde lors de l'utilisation de DiffFormatter et DiffEntry. Lorsque vous examinez le diff d'un espace de travail qui n'a pas organisé la modification (non enregistré dans l'index). (Bien sûr, lorsque vous regardez le diff dans l'espace de travail, c'est-à-dire dans git diff, il est normal que vous ne soyez pas mis en scène.)

        final Git git = new Git(repository);
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final List<DiffEntry> entryList = git.diff()
                .setCached(false)
//                .setOutputStream(bos)
                .call();

        final DiffFormatter fmt = new DiffFormatter(bos);
        fmt.setRepository(repository);
        fmt.format(entryList);
        final String text = new String(bos.toByteArray(), StandardCharsets.UTF_8);

Cela lèvera une org.eclipse.jgit.errors.MissingObjectException. Il n'y a aucun problème avec git.diff (). SetCached (true) .call () qui est équivalent à git add --cached.

** Ensuite, j'écrirai la cause et le remède, mais il n'y a aucun mérite pratique. ** ** Dédié à ceux qui ont des problèmes ou qui ont du mal à écrire du code comme celui ci-dessus.

Il existe deux types de cibles diff

Il existe deux types de cibles diff dans git.

La base de données git vous permet de récupérer un fichier compressé avec la valeur de hachage du fichier, qui est un objet blob. git add En d'autres termes, lorsque vous mettez en scène, il est calculé et créé à partir du fichier modifié et enregistré dans l'index. Vous pouvez également le créer avec la commande git hash-object -w.

DiffFormatter est une paire de ContentSource pour diff. .Pair](http://download.eclipse.org/jgit/site/4.8.0.201706111038-r/apidocs/org/eclipse/jgit/diff/ContentSource.Pair.html). Il existe deux façons de créer un ContentSource, selon les deux types de cibles de différence.

Cependant, lorsque format (DiffEntry ent) est terminé, ContentSource.Pair est ContentSource pour les objets blob. Et les modifications de l'espace de travail (fichiers modifiés) qui ne sont pas intermédiaires n'existent pas en tant qu'objets blob dans la base de données git.

Le résultat est une org.eclipse.jgit.errors.MissingObjectException. C'est également le cas avec la méthode FileHeader to FileHeader (DiffEntry ent).

Dans un tel cas, à l'intérieur de git.diff (). Call (), le code est le suivant (hors jugement et autres). Si vous faites la même chose, il sera envoyé normalement vers OutputStream.

        fmt.setRepository(repository)
        final AbstractTreeIterator oldTree = new DirCacheIterator(repository.readDirCache());
        final AbstractTreeIterator newTree = new FileTreeIterator(repository);
        fmt.scan(oldTree, newTree);

Ce [Scan <DiffEntry> (AbstractTreeIterator a, AbstractTreeIterator b)](http://download.eclipse.org/jgit/site/4.8.0.201706111038-r/apidocs/org/eclipse/jgit/diff/DiffFormatter. La méthode html # scan-org.eclipse.jgit.treewalk.AbstractTreeIterator-org.eclipse.jgit.treewalk.AbstractTreeIterator-) n'existe pas à cette fin, mais il existe une autre ContentSource DiffFormatter. Il n'y a aucun moyen de le changer de l'extérieur.

Maintenant, pour sortir le diff de la DiffEntry de la valeur de retour de ** git.diff (). Call (), il est décidé d'utiliser la méthode de balayage et la méthode de format de DiffFormatter **. Cependant, comme la valeur de retour de la méthode de scan est également DiffEntry, git.diff (). Call () est inutile, merci.

untracked files

Je ne sais pas si c'est le résultat attendu ou non implémenté, mais la commande Diff de JGit inclut également des ** fichiers non suivis ** dans le diff. En d'autres termes, git.diff (). Call (), qui devrait être l'équivalent de git diff, compare l'objet filelob non suivi enregistré dans index avec le fichier d'espace de travail tel quel.

commander old new
git diff Fichiers de l'espace de travail (fichiers non suivis)sauf Objet Blob enregistré dans l'index
git.diff().call() by JGit Fichiers de l'espace de travail (fichiers non suivis)Comprenant Objet Blob enregistré dans l'index

Je ne pense pas qu'il y en ait beaucoup lorsque vous voulez voir des différences et que vous ne voulez pas voir de fichiers non suivis, donc je pense que le comportement de JGit n'est pas si problématique. Il serait préférable de le spécifier en option.

L'émission d'un diff de fichiers non suivis avec la commande git est un peu fastidieuse.

git ls-files -o --exclude-standard

Vous pouvez obtenir la liste avec et obtenir le diff avec la commande suivante.

git diff --no-index /dev/null [untracked file name]

Soyez assuré que même Windows se comparera à / dev / null. Si vous voulez juste voir la différence, c'est un nouveau fichier, donc vous pouvez regarder le fichier lui-même, Dans le contexte actuel, ce que je veux, c'est un diff de format de patch qui puisse être appliqué, je l'ai donc présenté ici.

Espace de travail? Arbre de travail?

Quand je dis "works space diff", il semble étrange que le diff ne contienne pas de fichiers non suivis.

Mais git diff est-il un" espace de travail "et un index diff en premier lieu? Au moins "workspace" n'est pas un terme git, donc Peut-être que la réalité est que vous êtes confus en utilisant des mots arbitraires.

Le mot espace de travail est rarement utilisé dans la documentation officielle, https://git-scm.com/search/results?search=workspace https://git-scm.com/search/results?search=work%20space

Le mot arbre de travail est souvent utilisé. https://git-scm.com/search/results?search=worktree https://git-scm.com/search/results?search=work%20tree

C'est un défi car nous ne savons pas exactement ce que signifie le mot arbre de travail.

apply

ApplyCommand et git apply --cached

** La conclusion que j'ai obtenue dans le numéro précédent était "Pour mettre en scène les unités de ligne, créez un correctif qui reflète les changements des unités de ligne et git apply --cached" **. (Git apply -R --cached pour unstage ligne par ligne.)

Comme DiffCommand pour diff, apply a ApplyCommand .. Et la description de la classe JavaDoc dit:

Apply a patch to files and/or to the index.

Cependant, ApplyCommand ne peut pas appliquer le correctif à l'index. Ce n'est pas possible. Contrairement à DiffCommand, il n'y a pas de méthode comme setCached (). Même si vous regardez Source, enfin Il me semblait que j'étais en train d'écrire un fichier et de définir des autorisations.

https://github.com/eclipse/jgit/blob/6dab29f4b578bc164acb77083440e4087ed94ff4/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java#L262


		FileWriter fw = new FileWriter(f);
		fw.write(sb.toString());
		fw.close();

		getRepository().getFS().setExecute(f, fh.getNewMode() == FileMode.EXECUTABLE_FILE);

J'étais troublé.

Git apply comme compilation jusqu'à présent

J'ai confirmé que vous ne pouvez le faire qu'avec «Appliquer un correctif aux fichiers» en suivant les étapes ci-dessous.

  1. Modifiez le fichier
  2. Créez un patch
  3. Annuler les modifications de fichier
  4. Passez le correctif à ApplyCommand

À l'étape 2, utilisez DiffCommand pour générer une sortie dans un fichier et à l'étape 4, passez le fichier à ApplyCommand. C'est une compilation pour l'instant.

AddCommand et ResetCommand

Git add pour effectuer l'étape pour chaque fichier, équivalent [AddCommand](http://download.eclipse.org/jgit/site/4.8.0.201706111038-r/apidocs/org/eclipse/jgit/api/AddCommand Il y a .html). Il est difficile de penser qu'il a plus que git add en premier lieu, JGit n'est pas une copie complète de git, donc si vous regardez la liste des méthodes en l'attendant, ʻAjouter le jeu de commandes WorkingTreeIterator (WorkingTreeIterator f) `Il y a un léger espoir que la puissance de WorkingTreeIterator qui peut lui être transmise puisse être gérée d'une manière ou d'une autre. Cependant, ResetCommand n'a pas de méthode similaire, alors faites un suivi. Arrêtons-nous.

J'ai essayé de trouver un fichier qui lui ressemblait sérieusement, mais je ne l'ai pas trouvé. C'était une relation courte, mais il semble qu'il soit temps de dire au revoir à JGit.

CRLF

Un autre point avant les adieux.

Normalement (?) Dans un environnement Windows, un CRLF se brise.

Ensuite, définissez la fonction autocrlf sur true, validez avec LF et récupérez à distance avec CRLF. Cela devrait être officiellement recommandé. Je pense qu'il y avait une recommandation dans l'installateur. (Cependant, c'est ennuyeux car il y a des moments où vous voulez aller chercher comme LF.)

JGit vérifie si l'espace de travail et le correctif sont censés correspondre à la situation avant d'appliquer. Il semble que CRLF n'est pas pris en compte dans cette comparaison, et chaque ligne est interprétée comme ayant un CR à la fin. cr.PNG Et parce que chaque ligne ne correspond pas, elle lève org.eclipse.jgit.api.errors.PatchApplyException.

Si le correctif lui-même est défini sur CRLF, il ne sera pas reconnu comme un correctif valide. C'est également le cas avec la commande git Il semble que CL soit correct.

Avis de numéro suivant

git.exe

Il existe également un moyen de se lancer dans un voyage à la découverte de la bibliothèque suprême, Non limité à JGit, mais également lié à libgit2 et à d'autres bibliothèques Vous pouvez rencontrer des problèmes de manque de fonctionnalités. Par conséquent, à partir du prochain numéro, nous utiliserons git.exe, qui est une application git qui possède les meilleures fonctions. Il peut y avoir des difficultés à gérer différents processus, Il semble que vous serez en mesure d'acquérir des connaissances qui peuvent être comprises dans d'autres langues et environnements.

workaround

Étonnamment (?) Je ne sais pas si c'est un bug ou une spécification, Que ce soit la commande git ou le git-gui fourni avec le git lui-même Il y a quelques modèles que je viens de remarquer qui ne peuvent pas être mis en scène / désétagés normalement.

Le prochain numéro présentera principalement ces problèmes et les contournera.

Peut-être que le monde ne fait pas de mise en scène / de mise en scène ligne par ligne. Ensuite, il est logique de le faire vous-même.

Note de l'éditeur

Je l'ai ressenti avant d'écrire le numéro précédent "Basic Knowledge". Plus vous utilisez la commande git, plus vous êtes familiarisé avec la CLI. Sachez que certaines personnes perdent la motivation de créer un client GUI git.

Recommended Posts

Faire une capture incomplète de l'étape / unstage du client GUI hebdomadaire [2]
Créer un client GUI hebdomadaire git [4] diff et al.
Créer un client GUI hebdomadaire [5] Première application de bureau