Przejdź do pierwszej, poprzedniej, następnej, ostatniej sekcji, spisu treści.


9. Scalanie za pomocą patch

patch pobiera wyjście z porównania dokonanego przez diff i wprowadza różnice do kopii oryginalnego pliku, tworząc załataną wersję. Za pomocą patch można dystrybuować tylko zmiany jakiegoś zestawu plików, zamiast rozpowszechniania całości plików. Odbiorcy mogą zastosować łatę do aktualizacji swoich egzemplarzy plików do naszych zmian. patch automatycznie rozpoznaje typ pliku różnicy, pomija ewentualne początkowe i końcowe nagłówki i korzysta z nagłówka do stwierdzenia, który plik należy załatać. Umożliwia to naszym odbiorcom podawanie artykułów czy wiadomości zawierających listing różnic wprost do patch.

patch wykrywa typowe problemy, jak np. łaty odwrócone, i ostrzega o nich. Zachowuje oryginalne wersje łatanych plików i zapisuje wszystkie łaty, których nie dało się nałożyć. Potrafi także prowadzić plik patchlevel.h, by zagwarantować, że odbiorcy zastosują łaty w poprawnej kolejności.

patch przyjmuje ze swego standardowego wejścia ciąg różnic, zwykle rozdzielonych nagłówkami, podającymi jaki plik ma być załatany. Stosuje porcje diff (zob. 1.1. Porcje) jedną po drugiej. Jeśli porcja nie pasuje dokładnie do oryginalnego pliku, wówczas, starając się jak najlepiej go załatać, stosuje algorytm heurystyczny. Jeśli nie uda się znaleźć przybliżonego dopasowania, program odrzuca tę porcję i przechodzi do następnej. Normalnie patch każdy łatany plik f zastępuje jego nową wersją, pierwotną zachowuje w `f.orig', zaś odrzucone porcje (jeśli wystąpiły) w `f.rej'.

Zob. 14. Wywołanie patch, gdzie podano szczegółowy opis opcji patch. Zob. 14.2. Nazwy plików kopii zapasowych, gdzie dokładniej opisano, w jaki sposób patch nazywa pliki kopii zapasowych. Zob. 14.3. Nazwy plików odrzuceń, gdzie dokładniej opisano, gdzie patch umieszcza odrzucone porcje.

9.1. Wybór formatu wejściowego patch

patch normalnie ustala, którego formatu diff używa plik łaty badając jego zawartość. Dla plików łat zawierających szczególnie mylący tekst początkowy do wymuszenia poprawnej interpretacji formatu różnicy może zajść potrzeba użycia jednej z niżej wymienionych opcji. Podane tu formaty wyjściowe są jedynymi, jakie potrafi rozpoznać patch.

`-c'
`--context'
różnica kontekstowa.
`-e'
`--ed'
skrypt ed.
`-n'
`--normal'
normalny format różnicowy.
`-u'
`--unified'
różnica zunifikowana.

9.2. Nakładanie niedoskonałych łat

patch usiłuje pominąć ewentualny tekst początkowy z pliku łaty, nałożyć różnicę, a następnie pominąć tekst końcowy. Dzięki temu można przekazać artykuł z grupy dyskusyjnej czy wiadomość pocztową wprost do patch, i powinno to działać. Jeśli całość różnicy jest wcięta o stałą ilość białych znaków, wcięcie jest ignorowane automatycznie.

Jednak pewne inne rodzaje niedoskonałości wejścia wymagają interwencji użytkownika.

9.2.1. Nakładanie łat przy zmienionych odstępach

Czasami programy pocztowe, edytory czy inne programy wymieniają spacje na tabulacje lub odwrotnie. Jeśli zdarzy się to plikowi łaty albo wejściowemu, to mogą one wyglądać tak samo jak wcześniej, ale patch nie będzie mógł ich poprawnie dopasować. Jeśli pojawi się taki problem, należy zastosować opcję `-l' lub `--ignore-white-space', która powoduje, że program mniej rygorystycznie porównuje białe znaki, tak że dowolny ciąg białych znaków z pliku łaty pasuje do dowolnego ciągu białych znaków pliku wejściowego. Znaki nie będące białymi znakami w dalszym ciągu muszą pasować dokładnie. Każda linia kontekstu musi nadal odpowiadać odpowiedniej linii w pliku wejściowym.

9.2.2. Nakładanie odwróconych łat

Zdarza się, że ludzie uruchamiają diff z nowym plikiem jako pierwszym parametrem, zamiast jako drugim. Tworzy to łatę, która jest "odwrócona" ("reversed"). W celu nałożenia takiej łaty należy podać patch opcję `-R' lub `--reverse'. Program próbuje wówczas zamienić znaczenie każdej porcji przed jej nałożeniem. Odrzucenia wychodzą w formacie zamienionym. Opcja `-R' nie działa ze skryptami ed, gdyż zawierają zbyt mało danych do zrekonstruowania operacji odwrotnej.

Często patch potrafi się domyśleć, że łata jest odwrócona. Jeśli pierwszej porcji z łaty nie udaje się nałożyć, program odwraca tę porcję, by sprawdzić, czy da się jej użyć w ten sposób. Jeśli tak, to pyta użytkownika, czy chce on uaktywnienia opcji `-R'. Jeżeli się nie da -- łata będzie nakładana dalej w normalny sposób. Ta metoda nie jest w stanie wykryć łaty odwróconej jeśli różnica ma format normalny, a pierwszym poleceniem jest dopisanie (a powinno to być usunięcie). Jest tak dlatego, że dopisanie zawsze działa, gdyż pusty kontekst pasuje wszędzie. Szczęśliwym trafem, wiele łat raczej dodaje lub zmienia linie niż je usuwa, więc większość odwróconych różnic typu normal zaczyna się od usunięcia, które się nie udaje, dzięki czemu patch może zauważyć odwrócenie.

Jeśli nakładamy łatę, która już wcześniej została nałożona, patch sądzi, że jest to łata odwrócona i proponuje jej zdjęcie. Można to interpretować jako zaplanowaną cechę programu. Jeżeli zrobiliśmy to niechcący i nie chcemy zdejmować łaty, wystarczy odpowiedzieć `n' na tę propozycję i następujące po niej pytanie "nałożyć mimo to" ("apply anyway") -- lub nacisnąć C-c, by przerwać proces patch.

9.2.3. Pomoc patch w znalezieniu niedokładnych dopasowań

Dla różnic kontekstowych, i w mniejszym stopniu normalnych, patch potrafi wykryć wystąpienie w łacie niepoprawnych numerów linii i próbuje znaleźć właściwe miejsca do nałożenia poszczególnych porcji. Jako pierwszą próbę bierze linię o numerze podanym w łacie plus lub minus ewentualne przesunięcie zastosowane przy nakładaniu poprzedniej porcji. Jeśli nie trafi w poprawne miejsce, to przegląda plik w przód i wstecz szukając zestawu linii pasujących do kontekstu podanego w porcji.

patch początkowo szuka miejsca, do którego pasują wszystkie linie kontekstu. Jeśli nie może go znaleźć i ma do czynienia z różnicą kontekstową lub zunifikowaną, zaś maksymalny współczynnik rozmycia ma wartość co najmniej 1, to wykonuje kolejne wyszukiwanie ignorując pierwszą i ostatnią linię kontekstu. Jeśli się i to zawiedzie, a maksymalny współczynnik rozmycia jest równy co najmniej 2, to wykonuje następne wyszukiwanie, tym razem ignorując dwie pierwsze i dwie ostatnie linie kontekstu. Dalej postępuje podobnie jeśli współczynnik rozmycia jest większy.

Opcja `-F linie' lub `--fuzz=linie' nadaje maksymalnemu współczynnikowi rozmycia wartość linie. Opcja ta ma zastosowanie tylko różnic kontekstowych i zunifikowanych. Powoduje ignorowanie do linie linii podczas szukania miejsca do zainstalowania porcji. Należy pamiętać, że większy współczynnik rozmycia podnosi ryzyko błędnego załatania. Domyślnie współczynnik rozmycia wynosi 2. Nie można mu przypisać wartości większej niż ilość linii kontekstu w pliku różnicy, zwykle 3.

Jeżeli patch nie może znaleźć miejsca, w którym powinien zainstalować porcję łaty, zapisuje taką porcję do pliku odrzuceń (zob. 14.3. Nazwy plików odrzuceń, gdzie dokładniej opisano, jak nazywane są pliku odrzuceń). Odrzucone porcje zapisywane są w formacie kontekstowym, niezależnie od postaci łaty wejściowej. Jeśli ma ona format normalny lub skryptu ed, wiele kontekstów będzie po prostu pustych. Numery linii w pliku odrzuceń mogą być inne niż w łacie. Pokazują przybliżone miejsca w nowym pliku, do których, jak przypuszcza patch, należą wadliwe porcje. Numery linii nie odnoszą się do położenia w starym pliku.

Po zakończeniu obróbki każdej porcji, patch informuje, czy udało się ją zaaplikować czy nie. A jeśli nie, to w której linii (w nowym pliku) powinna się ona, według niego, znaleźć. Jeśli numer tej linii jest inny niż numer linii podany w pliku różnicy, pokazywane jest przesunięcie (offset). Pojedyncze duże przesunięcie może wskazywać na to, że patch zainstalował porcję w złym miejscu. Jeśli do dopasowania program skorzystał ze współczynnika rozmycia, to również o tym powiadamia, gdyż wówczas także powinniśmy być troszkę podejrzliwi.

patch nie umie stwierdzić, czy w skrypcie ed wyłączono numery linii. Potrafi wykryć błędne numery linii w różnicy normalnej tylko wtedy, gdy znajdzie polecenie zmiany lub usunięcia. Może mieć takie same kłopoty z różnicą kontekstową stosując współczynnik rozmycia równy liczbie linii kontekstu pokazanych w różnicy (standardowo 3) lub większy. W tych przypadkach powinno się zapewne obejrzeć różnicę kontekstową między oryginalnym plikiem wejściowym a załatanym, by stwierdzić czy zmiany mają sens. Bezbłędna kompilacja pliku jest całkiem dobrą wskazówką, że łatę nałożono poprawnie, ale nie daje gwarancji.

patch zwykle tworzy poprawne wyniki, nawet jeśli musi wielokrotnie korzystać z szacunków. Jednak wyniki są na pewno dobre tylko wtedy, gdy łata jest nakładana na dokładną kopię pliku, z którego została wygenerowana.

9.3. Usuwanie pustych plików

Czasem podczas porównywania dwu katalogów zdarza się, że pierwszy z nich zawiera plik, którego nie ma w drugim. Jeśli podamy diff opcję `-N' lub `--new-file', to wypisze różnicę, która usuwa zawartość tego pliku. Domyślnie, patch po przetworzeniu takiej różnicy pozostawia pusty plik. Użycie patch z opcją `-E' lub `--remove-empty-files' powoduje usunięcie plików wyjściowych, które po nałożeniu łaty są puste.

9.4. Wiele łat w pliku

Jeżeli plik łaty zawiera więcej niż jedną łatę, to patch usiłuje zastosować każdą z nich tak, jakby pochodziły z osobnych plików łat. Oznacza to, że program określa nazwę pliku do załatania osobno dla każdej łaty i bada tekst przed każdą z nich szukając nazw plików i wymaganych wstępnie numerów wersji (zob. 10. Wskazówki, jak tworzyć rozsyłane łaty, gdzie jest więcej na ten temat).

Dla drugiej i kolejnych łat w pliku można podać opcje i zastępczą nazwę oryginalnego pliku oddzielając ich listy argumentów znakiem plus `+'. Lista argumentów dla drugiej i następnych łat nie może jednak wskazywać nowego pliku łaty, gdyż nie ma to sensu.

Na przykład, chcąc nakazać patch wycięcie pierwszych trzech ukośników z nazwy pierwszej łaty w pliku, a niewycinanie ich w ogóle z kolejnych, oraz użycie `code.c' jako pierwszego pliku wejściowego, stosujemy:

patch -p3 code.c + -p0 < plikłaty

Opcja `-S' lub `--skip' powoduje, że program ignoruje aktualnie rozpatrywaną łatę, ale dalej szuka kolejnej łaty w pliku. Zatem, do zignorowania pierwszej i trzeciej łaty w pliku łat używamy:

patch -S + + -S + < plikłaty

9.5. Komunikaty i pytania programu patch

patch może dawać rozmaite komunikaty, szczególnie, jeśli ma kłopoty z odczytaniem i zrozumieniem podanego mu wejścia. W nielicznych sytuacjach, gdy nie jest pewien, jak postąpić, normalnie prosi o podanie z klawiatury dodatkowych informacji. Istnieją opcje wyłączające wypisywanie komunikatów (jeśli błędy nie są krytyczne) i oczekiwanie na dane z klawiatury.

Komunikat `Hmm...' wskazuje, że patch właśnie czyta tekst z pliku łatającego, usiłując stwierdzić, czy jest w nim łata, a jeśli tak, to jakiego rodzaju.

Opcja `-s', `--quiet' lub `--silent' zakazuje wysyłania na terminal wszelkiego wyjścia, chyba że pojawi się błąd.

Są dwa sposoby powstrzymania patch od zadawania pytań. Opcja opcją `-f' lub `--force' wymusza założenie, że użytkownik dokładnie wie co robi. Program działa wówczas według poniższych reguł:

Opcja `-t' lub `--batch' jest podobna do `-f', gdyż również eliminuje pytania, ale powoduje przyjęcie nieco innych założeń:

patch kończy działanie z niezerowym kodem zakończenia jeśli utworzył jakieś pliki odrzuceń. Nakładając w pętli zestaw łat, powinno się sprawdzać kod zakończenia, by nie nałożyć późniejszej łaty na plik tylko częściowo załatany.


Przejdź do pierwszej, poprzedniej, następnej, ostatniej sekcji, spisu treści.