aragost Trifork: Mercurial Kick Start Exercises


Subrepozitáře

Obsah

Úvod

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

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.

Vzdálené subrepozitáře

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í.

Subrepozitáře Subversion

Ř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.

Práce se subrepozitáři

Nyní si ukážeme praktické používání subrepozitářů.

Komitování

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.

Pušing a puling

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.

Jiná verze

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 na požádání

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 překračující hranice repozitářů

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.

Tipy a triky

Na závěr si vysvětlíme, jak provádět některé neobvyklé, nicméně docela užitečné operace.

Přeměna složky na subrepozitář

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

Odpojení subrepozitáře

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ů.

Cvičení

  1. Použijte hg init pro vytvoření repozitáře kick-start, přidejte do něho soubor .hgsub a vytvořte subrepozitář mysubrepo.

  2. Příkazy hg add a hg commit proveďte několik komitů. Totéž zkuste v subrepozitáři se --subrepos opcemi.

  3. Použijte hg update v subrepozitáři pro přesun ke starší revizi.

  4. Přejděte k hlavním repozitářům. Použijte hg status ke zjištění, že subrepozitář …

  5. Použijte hg commit k aktualizaci registrované revize subrepozitáře. Komit nebude prázdný, protože zahrnuje soubor .hgsubstate.

  6. Přidejte repozitář SVN jako subrepozitář.