Obsah
Mercurial obsahuje proceduru, zvanou subrepozitář. Tato procedura umožňuje zacházet s kolekcí repozitářů jako se skupinou.
Opětovné používání kódu je důležitým konceptem skladby programu. Subrepozitáře toto opětovné použití podporují svými sdílenými knihovnami a moduly.
Subrepozitáře lze vnořovat jeden do druhého.
Základní příkazy pro subrepozitáře jsou stejné, jako pro normální repozitáře. Subrepozitáře jsou zahrnuty do operace doplněním příkazu opcí --subrepo.
Při provádění přikazu uvnitř pracovního adresáře subrepozitáře bude chování úplně stejné, jako mimo subrepozitář; subrepozitář nepozná, že je uvnitř jiného repozitáře.
Subrepozitáře jsou vlastně normální repozitáře; vytvoříme je tak, že je nejprve vytvoříme uvnitř jiného repozitáře příkazem hg init:
alice$ hg init mainrepo alice$ cd mainrepo alice$ hg init subrepo alice$ ls subrepo
Vytvořili jsme nyní dva repozitáře, jeden vnořený do druhého. To ale z vnořeného repozitáře ještě subrepozitář nedělá. Vnořený repozitář musí být vnějším repozitářem veden jako subrepozitář.
Označení subrepozitáře se provede zápisem ve specielním souboru .hgsub. Vloží se následující řádek:
alice$ echo subrepo = subrepo > .hgsub alice$ hg add .hgsub
Poznámka
Soubor .hgsub lze interpretovat přiřazením ve tvaru:
where/to/put/the/subrepo = where/to/get/the/subrepo
Na levé straně je relativní cesta k místu umístění subrepozitáře.
Na pravé straně je buď relativní nebo absolutní cesta k místu, odkud má být klon převzat. Příkazem hg clone mainrepo my-main, vytvoří Mercurial nový repozitář v my-main/where/to/put/the/subrepo a naplní jej changesety, převzatými z mainrepo/where/to/get/the/subrepo.
V jednoduchém případě, kdy ‘subrepo = subrepo’, provedete v Mercurialu tyto příkazy:
$ hg clone http://server/repos/repo my-repo $ cd repo $ hg clone http://server/repos/repo/subrepo $ cd ..
a jestliže jste použil přiřazení subrepo = ../subrepo, potom ony příkazy budou:
$ hg clone http://server/repos/repo my-repo $ cd repo $ hg clone http://server/repos/subrepo $ cd ..
kde poslední URL je normalizovaná verze http://server/repos/repo/../subrepo.
Chceme také připojit vzdálený repozitář k našemu projektu. Tato procedura je podobná předchozí:
alice$ hg clone http://www.selenic.com/repo/hello remoterepo requesting all changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 2 files updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved alice$ echo remoterepo = http://www.selenic.com/repo/hello >> .hgsub alice$ ls remoterepo subrepo
Všimněte si, že klonujeme repozitář přesně tam, kde má být, protože pouhé přidání zápisu do souboru .hgsub nic nezmění, pokud na uvedeném místě repozitář není.
Řekněme, že jistá společnost má knihovny v repozitářích Subversion a z nějakých důvodů je nemůže konvertovat do Mercurialu. To není problém, protože Mercurial umí používat repozitáře Subversion jako subrepozitáře. Postup je stejný jako výše až na to, že v souboru .hgsub předsadíme [svn] před URL.
Proto přidání subrepozitáře SVN bude vypadat následovně:
alice$ svn co http://mercurial.aragost.com/svn/hello/trunk svnrepo A svnrepo/hello.c A svnrepo/Makefile A svnrepo/README U svnrepo Checked out revision 10. alice$ ls remoterepo subrepo svnrepo alice$ echo svnrepo = [svn]http://mercurial.aragost.com/svn/hello1/trunk >> .hgsub
Potom se příkazy SVN používají v subrepozitáři a příkazy Mercurialu v nadřazeném repozitáři.
Nyní si ukážeme praktické používání subrepozitářů.
Status lze jako vždy zjistit příkazem hg status, pouze pro subrepozitáře připojíme opci --subrepo. Přitom soubory ze subrepozitáře budou reflektovány až po předání¨ (komitu) souboru .hgsub.
alice$ hg status A .hgsub
Naše změny ještě komitovány nejsou, pročež tak učiníme.
alice$ hg commit -m "Subrepositories added" alice$ hg status alice$ hg status --subrepos
Implicitní chování komitu je takové, že se nejprove provedou komity v subrepozitářích a potom se provedou komity ve vnějším repozitáři. Výsledný stav subrepozitářů je uložen ve speciálním souboru zvaném .hgsubstate; tento soubor nemá být editován uživatelem.
Mercurial se vždy pokusí nejprve poslat (push) všechny subrepozitáře před vlastním repozitářem, čímž se zajistí, že se v cílovém repozitáři neobjeví odkazy na neexistující verzi subrepozitáře.
Stahování (pulling) na druhou stranu nemá rekursivní povahu, protože Mercurial nemůže vědět které subrepozitáře má stáhnout před tím, než se provede aktualizace k určitému changesetu.
Jak bylo zmíněno, .hgsubstate se nemá editovat. Pokud ale chcete subrepozitář přepnout na jinou revizi, potom do něho vstupte a k této revizi jej aktualizujete. Tato změna musí být také zaznamenána ve vnějším repozitáři. V něm tedy provedete komit, což změní stav subrepozitáře v souboru .hgsubstate.
Nejprve provedeme nějaké změny a komitujeme je v subrepozitáři, potom provedeme finální komit pro aktualizaci souboru .hgsubstate.
alice$ cd subrepo alice$ echo a > a.txt alice$ hg add a.txt alice$ hg commit -m "A" alice$ echo b > b.txt alice$ hg add b.txt alice$ hg commit -m "B" alice$ echo c > c.txt alice$ hg add c.txt alice$ hg commit -m "C" alice$ cd .. alice$ hg commit -m "Main repo"
Nyní je hlavní repozitář propojen s nejnovější revizí subrepozitáře. Chceme ale propojit hlavní repozitář s dřívější verzí subrepozitáře. Provede se to tak, že aktualizujeme subrepozitář k žádané revizi a provedeme komit v hlavním repozitáři, abychom aktualizovali soubor .hgsubstate.
alice$ cd subrepo alice$ hg log changeset: 2:50b194df1a80 tag: tip user: Alice <alice@example.net> date: Wed Mar 10 20:12:05 2010 +0000 summary: C changeset: 1:00bd589746e0 user: Alice <alice@example.net> date: Wed Mar 10 20:11:05 2010 +0000 summary: B changeset: 0:3cf2ce324347 user: Alice <alice@example.net> date: Wed Mar 10 20:10:05 2010 +0000 summary: A alice$ hg update 1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved alice$ cd .. alice$ hg commit -m "Changed subrepo version"
Aktualizace také přirozeně provádí akce se subrepozitáři, protože aktualizace repozitáře k jiné revizi může znamenat, že musíme také k jiné revizi aktualizovat subrepozitář.
Jak již bylo zmíněno, soubor .hgsubstate zaznamenává revizi subrepozitáře, která má být užita. Proto nevíme, kterou verzi subrepozitáře aktualizovat před konzultací s tímto souborem. Proto je nejprve aktualizován repozitář a potom subrepozitáře podle aktualizované verze souboru .hgsubstate. To může také zahrnovat stahování z cesty subrepozitáře, nebyla-li revize souboru .hgsubstate dosud stažena (pulled).
Příkazy hg commit a hg update procházejí rekursivně subrepozitáři. Nebylo-li v subrepozitáři nic změněno, potom přirozeně se tento subrepozitář komitu nezůčastní.
Další příkazy, které by mohly pracovat se subrepozitářích, potřebují doplněk opcí --subrepos.
Jsou to příkazy gh add, gh archieve, hg diff, hg incoming, hg outgoing a hg status.
Příkaz hg add --suprepos umožňuje přidávat soubory do subrepozitáře se stejnou syntaxí jako u jiného adresáře.
Ostatní příkazy provádějí to, co normálně, zahrnou však i subrepozitáře, pokud jsou doplněny opcí --subrepos.
Na závěr si vysvětlíme, jak provádět některé neobvyklé, nicméně docela užitečné operace.
Projekt může obsahovat složku se skripty, které by v pozdějším stadiu měly být použity v různých projektech. Tyto skripty by ovšem mohly být jednoduše nakopírovány do repozitáře, které by pozdější projekty mohly použít jako subrepozitáře. To by ovšem znamenalo, že ztratíme cennou historii těchto souborů.
Provede se to tak, že se použije extenze convert (convert extension) a potom se tento repozitář včlení jako subrepozitář.
V první části dole se pouze vytvoří naše složka, provedou se nějaké změny, které se komitují.
alice$ mkdir folder alice$ echo 'infolder' > folder/1.txt alice$ hg add folder/1.txt alice$ ls folder remoterepo subrepo svnrepo alice$ hg commit -m "In folder" alice$ echo 'notinfolder' > 2.txt alice$ hg add 2.txt alice$ hg commit -m "Not in folder"
Nejde přeložit: Now we want to make the folder into a subrepository. First we just make the folder into an repository. This is done by converting the original repository from a Mercurial repository to a Mercurial repository and then using a filemap to specify we only want the certain folder.
Mapa souborů určuje, co má být zahrnuto do složky; navíc existuje mapování změn názvů, což zajišťuje, že obsah složky bude v kořenovém adresáři vytvářeného repozitáře bude. Potom provedeme konverzi a dohlédneme, že máme repozitář pouze s těmi changesety, které byly editovány uvnitř složky. Tento repozitář potom může být přičleněn jako subrepozitář, jak bylo dříve popsáno.
alice$ echo 'include folder' > map.txt alice$ echo 'rename folder .' >> map.txt alice$ hg --config extensions.hgext.convert= convert --filemap map.txt . mynewsubrepo initializing destination mynewsubrepo repository scanning source... sorting... converting... 4 Subrepositories added 3 Main repo 2 Changed subrepo version 1 In folder 0 Not in folder alice$ cd mynewsubrepo alice$ hg update 1 files updated, 0 files merged, 0 files removed, 0 files unresolved alice$ hg log changeset: 0:c505b3dd95a2 tag: tip user: Alice <alice@example.net> date: Wed Mar 10 20:13:05 2010 +0000 summary: In folder
Jestliže již subrepozitář nepotřebuje být spojován s projektem, potom jej oddělíme prostým smazáním odpovídajícího řádku v souboru .hgsub. Příkaz hg status tyto soubory potom bude zobrazovat jako neznáme a lze je smazat ze systému souborů.
Použijte hg init pro vytvoření repozitáře kick-start, přidejte do něho soubor .hgsub a vytvořte subrepozitář mysubrepo.
Příkazy hg add a hg commit proveďte několik komitů. Totéž zkuste v subrepozitáři se --subrepos opcemi.
Použijte hg update v subrepozitáři pro přesun ke starší revizi.
Přejděte k hlavním repozitářům. Použijte hg status ke zjištění, že subrepozitář …
Použijte hg commit k aktualizaci registrované revize subrepozitáře. Komit nebude prázdný, protože zahrnuje soubor .hgsubstate.
Přidejte repozitář SVN jako subrepozitář.