101 votes

Comment créer un patch pour un répertoire entier pour le mettre à jour?

Je sais qu'il existe déjà plusieurs fils de discussion à ce sujet, mais personne n'a vraiment expliqué comment effectuer la différence initiale pour créer le fichier de correctif, puis comment appliquer ce correctif au répertoire initial pour le mettre à jour.

Dans mon cas, il y a un répertoire de fichiers que tout le monde peut télécharger sur le web. J'ai pris ce répertoire et y ai apporté des modifications, et je veux créer un fichier de correctif de sorte que les autres puissent l'appliquer au répertoire téléchargé pour reproduire exactement ce que j'ai dans mon répertoire modifié.

Aide ? Que dois-je dire à l'autre personne concernant la manière d'appliquer mon correctif ?

186voto

David H Points 23654

J'ai rencontré le même problème - beaucoup de conseils sur la manière de le faire à moitié. Eh bien, voici ce que j'ai fait pour que à la fois le patching et le unparching fonctionnent:

Pour créer le fichier de patch :

  1. Mettez des copies des deux répertoires dans, disons, /tmp, afin que nous puissions créer le fichier de patch, ou si vous êtes courageux, mettez-les côte à côte - dans un seul répertoire.

  2. Exécutez une commande diff appropriée sur les deux répertoires, ancien et nouveau :

    diff -ruN orig/ new/ > file.patch
    # -r == récursif, donc faire les sous-répertoires
    # -u == style unifié, si votre système ne le supporte pas ou si le destinataire
    #       ne le possède pas, utilisez "-c"
    # -N == traiter les fichiers absents comme vides

Si une personne a le répertoire orig/, elle peut recréer le nouveau en exécutant le patch.

Pour recréer le nouveau dossier à partir du dossier ancien et du fichier de patch :

  1. Déplacez le fichier de patch dans un répertoire où se trouve le répertoire orig/

  2. Ce répertoire sera écrasé, alors gardez-en une sauvegarde quelque part, ou utilisez une copie.

    patch -s -p0 < file.patch
    # -s == silencieux sauf erreurs
    # -p0 == nécessaire pour trouver le dossier approprié
  3. À ce stade, le répertoire orig/ contient le contenu de new/, mais il garde son ancien nom, donc :

    mv orig/ new/    # si les noms des dossiers sont différents

14voto

Zack Morris Points 560

J'avais besoin de créer un fichier de correctif et de l'envoyer à quelqu'un pour qu'il puisse mettre à jour son répertoire pour correspondre au mien. Il y a de nombreuses subtilités avec diff et patch, donc cela m'a pris des heures pour comprendre quelque chose de conceptuellement simple. Les chemins absolus semblent être préférés aux chemins relatifs, et bon nombre des options semblent avoir évolué à partir de cas d'utilisation de niche. J'ai finalement trouvé une solution basée sur la réponse de David H, avec des conseils supplémentaires de Lakshmanan Ganapathy) :

  • Sauvegardez votre répertoire sous répertoire.orig
  • Modifiez votre répertoire pour atteindre l'état désiré
  • Enregistrez la différence de répertoire.orig à répertoire dans file.patch pour que le nom corresponde pour le destinataire

Voici mes notes :

# pour créer un correctif :
# copiez la sauvegarde du répertoire dans quelque chose comme .orig à côté
cp -r / /.orig
# créez/mettez à jour/supprimez des fichiers/dossiers dans  jusqu'à ce que l'état désiré soit atteint
# changez de répertoire de travail vers 
cd /
# créez un fichier de correctif à côté de 
diff -Naru ../.orig . > ../file.patch
# -N --new-file Traiter les fichiers absents comme vides.
# -a --text Traiter tous les fichiers comme du texte.
# -r --recursive Comparer de manière récursive tous les sous-répertoires trouvés.
# -u -U NUM --unified[=NUM] Produire NUM (3 par défaut) lignes de contexte unifié.

# pour appliquer le correctif :
# changez de répertoire de travail vers 
cd /
patch -s -p0 < /file.patch
# -s or --silent or --quiet Travaillez en silence, sauf en cas d'erreur.
# -pN or --strip=N Supprimez le plus petit préfixe contenant num slashs initiaux des fichiers.

# pour annuler le correctif (notez que les répertoires créés par le correctif doivent être supprimés manuellement) :
# changez de répertoire de travail vers 
cd /
patch -Rs -p0 < /file.patch
# -R or --reverse Supposer que le correctif a été créé avec les anciens et les nouveaux fichiers échangés.
# -s or --silent or --quiet Travaillez en silence, sauf en cas d'erreur.
# -pN or --strip=N Supprimez le plus petit préfixe contenant num slashs initiaux des fichiers.

3voto

Alexey Baskakov Points 86

Découvrez la bibliothèque Scarab C++ open source : https://github.com/loyso/Scarab

Elle fait exactement ce que vous avez décrit. Elle génère une différence par fichier en utilisant la bibliothèque xdelta et la place dans un paquet d'archive. Vous pouvez redistribuer ce paquet et appliquer la différence. Il y a des binaires pour Win32.

Je suis l'auteur du projet Scarab.

2voto

Attention

Ne pas utiliser -p0 sauf si vous comprenez comment fonctionne patch.


Diff

Créez un .diff profond (récursif) entre deux répertoires dans le même répertoire parent. Un fichier .diff est un fichier qui décrit toutes les différences textuelles.

diff --unified --recursive --no-dereference ORIGINAL/ PATCHED/ > patch.diff
  • --unified : pour formater la sortie en un "différentiel de contexte unifié".
  • --recursive : pour créer un .diff profond.
  • --no-dereference : ne pas suivre les liens symboliques.

Bien que les noms de répertoire, ORIGINAL et PATCHED, soient inclus dans les chemins des fichiers en sortie, patch.diff, ils ne sont pas importants ("ne seront pas utilisés plus tard").

Patch

Avec le fichier patch.diff, vous pouvez appliquer des correctifs à n'importe quel répertoire de la même structure hiérarchique. Vous n'avez plus besoin des répertoires nommés ORIGINAL et PATCHED.

Par exemple, cette commande applique le correctif au répertoire directory_to_apply_the_patch_on/ selon le patch.diff.

patch --directory=directory_to_apply_the_patch_on/ --strip=1 < patch.diff
  • --directory : pour définir le répertoire de travail pour patch.

patch suppose que les chemins des fichiers dans patch.diff sont relatifs au répertoire de travail. Ces chemins ont un PATCHED/ précédent, donc vous devez d'abord le supprimer sauf si vous avez un répertoire PATCHED à patcher dans votre répertoire de travail.

--strip= ou -p supprime les N premiers segments (délimités par des barres obliques) des chemins de fichiers spécifiés dans le fichier patch.diff. --strip=1 supprime le répertoire supérieur PATCHED/ de tous les chemins de fichiers de destination, les rendant relatifs à directory_to_apply_the_patch_on/ à la place.

Vikram Dattu : est-il possible d'omettre ces noms de répertoire extérieurs ? Ou est-il nécessaire que le correctif contienne les noms de répertoire new et orig ?

Flimm : Est-il possible d'appliquer le correctif sans exiger que les répertoires nommés orig ou new existent ?

Oui, c'est ce que --strip=1 permet.

Pour moi, je préfère ceci :

patch --directory=directory_to_apply_the_patch_on/ --unified --strip=1 --posix --force --set-utc --verbose < patch.diff
  • --unified : pour interpréter le fichier .diff comme un diff de contexte unifié, en sautant les suppositions de format.
  • --posix : pour se comporter de manière conforme à POSIX.
  • --force : pour ne pas poser de questions en cas d'échec.
  • --set-utc : pour mettre à jour les heures de modification des fichiers patchés.
  • --verbose : pour imprimer ce qu'il pense en essayant d'appliquer le correctif.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X