Obtenir des affichages diff lisibles dans Mercurial sur les fichiers Unicode (MS Windows)

J’essaie de stocker certains scripts Windows PowerShell dans un référentiel Mercurial. Il semble que l’éditeur de PowerShell aime enregistrer des fichiers au format UTF-16 Unicode. Cela signifie qu’il y a beaucoup de \0 octets, ce que Mercurial utilise pour distinguer les fichiers “texte” des fichiers “binarys”. Je comprends que cela ne change rien à la façon dont Mercurial stocke les données, mais cela signifie qu’il affiche des différences binarys, ce qui est assez difficile à lire. Est-il possible de dire à Mercurial que ce sont vraiment des fichiers texte? Vraisemblablement, je devrais convaincre Mercurial d’utiliser un programme diff externe compatible avec Unicode pour des types de fichiers particuliers.

Cela peut ne pas être pertinent pour vous; lisez le dernier paragraphe si cela ne sonne pas comme il est.

Je ne suis pas sûr que ce soit ce dont vous avez besoin, mais j’ai besoin de diffs avec du contenu UTF-16LE plus que les “fichiers binarys sont différents” – lorsque j’ai cherché il y a quelques mois pour cela, j’ai trouvé un fil et bogue en discutant; en fait partie . Je ne trouve pas la source originale de cette mini-extension maintenant (bien qu’elle fasse exactement ce que fait ce patch), mais ce que j’ai eu était une extension, BOM.py :

 #!/usr/bin/env python from mercurial import hg, util import codecs boms = [ codecs.BOM_UTF8, codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE, codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE ] def binary(s): if s: for bom in boms: if s.startswith(bom): return False return '\0' in s return False def reposetup(ui, repo): util.binary = binary 

Ceci est chargé dans le .hgrc (ou vos utilisateurs \ username \ mercurial.ini) comme ceci:

 [extensions] bom = ~/.hgexts/BOM.py 

Notez que le chemin variera entre Windows et Linux; Sur ma copie Windows, je mets le chemin sous la forme \...\whatever (il se trouve sur un disque USB sur lequel la lettre du lecteur peut changer). Malheureusement, les chemins relatifs sont relatifs au répertoire de travail actuel plutôt qu’à la racine du référentiel ou à une telle chose, mais si vous l’enregistrez sur votre lecteur C:, vous pouvez simplement placer le chemin complet.

Dans Linux (mon environnement de développement principal), cela fonctionne bien; dans l’invite de commande (que j’utilise encore régulièrement), cela fonctionne généralement bien. Je ne l’ai jamais essayé dans PowerShell, mais je m’attendrais à ce qu’il soit meilleur que l’invite de commandes dans sa prise en charge des octets nuls arbitraires dans la ligne de commande.

Je ne sais pas si c’est ce que vous voulez du tout. Par la façon dont vous avez dit “diff binarys”, je soupçonne que vous avez déjà ce soit ou que vous faites hg diff -a qui réalise la même chose. Dans ce cas, tout ce que je peux penser à écrire est une autre extension qui prend l’UTF-16LE et tente de le décoder en UTF-8. Je ne suis pas sûr de la syntaxe pour une telle extension, mais je pourrais essayer cela.

Edit: après avoir passé la source mercurial à travers commands.py, cmdutil.py, patch.py ​​et mdiff.py, je vois que les diffs binarys se font avec un encodage base85 (patch.b85diff) plutôt qu’avec le diff normal. Je n’étais pas au courant de cela, je pensais que ça le forçait à le différencier. Dans ce cas, peut-être que ce texte est pertinent après tout. J’attends une réponse pour voir si c’est le cas!

J’ai contourné ce problème en créant un nouveau fichier avec NotePad ++ et en l’enregistrant sous forme de fichier PowerShell (extension .ps1). NotePad ++ va créer le fichier en tant que fichier ANSI en texte brut. Une fois créé, je peux ouvrir le fichier dans l’éditeur PowerShell et apporter les modifications nécessaires sans que l’éditeur ne modifie le codage du fichier.

Disclaimer: J’ai rencontré cela il y a quelques instants et je ne suis donc pas sûr qu’il y ait des répercussions, mais jusqu’à présent, mes scripts semblent fonctionner normalement et mes diffs apparaissent bien.

Si mon autre réponse ne fait pas ce que vous voulez, je pense que celle-ci peut; bien que je ne l’ai pas encore testé sur Windows, cela fonctionne bien sous Linux. Il fait ce qui est potentiellement une mauvaise chose, en encapsulant mercurial.mdiff.unidiff avec une nouvelle fonction qui convertit utf-16le en utf-8. Cela n’affectera pas hg st , mais affectera hg diff . Un écueil potentiel est que la nomenclature sera également modifiée de la nomenclature UTF-16LE à la nomenclature UTF-8.

Quoi qu’il en soit, je pense que cela peut vous être utile, alors le voici.

Fichier d’extension utf16decodediff.py :

 import codecs from mercurial import mdiff unidiff = mdiff.unidiff def new_unidiff(a, ad, b, bd, fn1, fn2, r=None, opts=mdiff.defaultopts): """ A simple wrapper around mercurial.mdiff.unidiff which first decodes UTF-16LE text. """ if a.startswith(codecs.BOM_UTF16_LE): try: # Gets reencoded as utf-8 to be a str rather than a unicode; some # extensions may expect a str and may break if it's wrong. a = a.decode('utf-16le').encode('utf-8') except UnicodeDecodeError: pass if b.startswith(codecs.BOM_UTF16_LE): try: b = b.decode('utf-16le').encode('utf-8') except UnicodeDecodeError: pass return unidiff(a, ad, b, bd, fn1, fn2, r, opts) mdiff.unidiff = new_unidiff 

Dans .hgrc :

 [extensions] utf16decodediff = ~/.hgexts/utf16decodediff.py 

(Ou chemins équivalents)