Hoe kan ik een patchbestand in kwik aanmaken dat ook de veranderingen bevat van ingesloten subrepo's

We werken met meerdere mensen aan hetzelfde project en gebruiken Mercurial als onze DVCS. Ons project heeft verschillende subrepos. We moeten patches per e-mail naar elkaar sturen, omdat het op dit moment onmogelijk is om te pushen en te trekken van de master repo. De exportopdracht - indien uitgevoerd op de master maakt alleen een patch voor de master en niet voor de subrepo's. We zouden er handmatig een pad voor kunnen creëren, maar we zouden graag willen weten of er een eenvoudigere manier is om dit te doen?

4
Je kunt me dom noemen, maar: waarom gebruik je DVCS als CVCS? Als teamgenoten kunnen mailen, kunnen ze zich terugtrekken uit de repo van andere leden. hg serve werkt voor iedereen
toegevoegd de auteur Lazy Badger, de bron

3 antwoord

Er is geen ingebouwde ondersteuning voor dit, zoals je hebt gemerkt.

Misschien kun je de onsub-extensie gebruiken die ik heb geschreven. Dat maakt het een beetje eenvoudiger om patches voor de subrepos te genereren:

$ hg onsub 'hg export -r tip -o $HG_REPO/sub-$HG_SUBPATH.diff' 

De variabele HG_SUBPATH wordt vervangen door het pad naar het subrepo.

Dat mislukt als je geneste subreposen hebt, omdat hg export geen patroonnamen sub-foo/bar/baz.diff kan schrijven. Dus je moet het pad masseren en / vervangen door - of iets dergelijks. U zou in staat moeten zijn om de patches te importeren met een soortgelijke hg onsub oproep.

Als je het werkt, voel je dan vrij om er een notitie over toe te voegen op de wikipagina. Je bent ook van harte welkom om te zien of je de extensie onsub kunt verlengen om dit gemakkelijker te maken, misschien door een optie toe te voegen om onsub op de repo op het hoogste niveau te laten draaien, en een nieuwe variabele die direct kan worden gebruikt in plaats van HG_SUBPATH .

1
toegevoegd
Aangezien we subrepos hebben genest, en ik ben niet erg bekend met Python, denk ik dat ik eerst in een aantal andere oplossingen moet zoeken. Ik moet ook een manier vinden om dit te doen met de TortoiseHg-worbench, omdat niet alle teamleden bekend zijn met het opdrachtvenster (we werken aan windows)
toegevoegd de auteur Johan, de bron
  • hg archief weet van subrepo: je kunt wijzigingen exporteren van enkele wijzigingenset (en ze lopen recursief, als subrepos beïnvloed worden tijdens commit)
  • hg diff weet ook van subrepos
  • in het geval van hg commit --subrepos dit commit moet ook alle betrokken bestanden bevatten van subrepos, dus - exporteert (?) deze bestanden ook
0
toegevoegd
hg archive can exporteer alleen bestanden, beïnvloed door gespecificeerde changeset - aanvinkvakje bij THG, -I op commandolijn (filelist kan worden opgehaald door hg log - testplate)
toegevoegd de auteur Lazy Badger, de bron
Ja, de opdracht archive kent subrepos, maar het is geen gemakkelijke manier om met de bestanden te werken, het is slechts een momentopname van de werkdirectory. De exportopdracht kent geen subrepos, omdat in mijn tests het patchbestand alleen het verschil van het .hgsubstate-bestand bevat. Het importeren van deze patch geeft 'onbekende revisiefouten' voor de subreposen.
toegevoegd de auteur Johan, de bron
Ja, maar dan moeten we die bestanden ook in de andere repo vastleggen. dit zal waarschijnlijk een aantal problemen geven als we elkaar kunnen ontmoeten en dan proberen onze repo's te synchroniseren
toegevoegd de auteur Johan, de bron

Zoals Martin suggereerde, schreef ik mijn eigen extensie. Ik zal de code hier plaatsen, in de hoop dat iemand het zal verbeteren of het beschikbaar zal maken in mercurial ...

Bedankt Martin, ik heb het gebaseerd op je extensie, en ja ik weet dat er een paar problemen mee zijn, maar voor nu, het dient zijn doel. (problemen met meer dan 10 subrepos en meer dan 1 nestniveau)

"""execute the Bundle command in a repository and each subrepository"""

# bundlesb.py - execute the Bundle command in a repository and each subrepository
#
# Copyright 2012 Johan G.
#
# This software may be used and distributed according to the terms of
# the GNU General Public License version 2 or any later version.

import os
import zipfile
from mercurial.i18n import _
from mercurial import extensions, subrepo, util

def bundlesb(ui, repo, *args, **opts):
    """execute the Bundle command in a repository and each subrepository

    Creates a combined bundle (with hgs extention) for the current 
    repository. 

    Because the revision numbers of the root and the subrepos will differ,
    we cannot reliably choose a revision to start from. A date to start
    from should be nice, but i have not taken the time to implement this.
    Instead i choose to take the N (default=10) last changesets into account.
    This seems to work well in our environment. Instead of providing the
    number of changesets for the operation, you can also specify -a to
    include all changesets. 

    Use --verbose/-v to print information and the subrepo
    name for each subrepo. 
    """
    ui.status("Starting operation\n")
    zipname = os.path.splitext(' '.join(args))[0]
    if (zipname==''):
       zipname = os.path.join(repo.root, os.path.split(repo.root)[1])
       #raise ValueError("FILE cannot be empty")
    zipname= zipname + '.hgs'
    allchangesets=opts.get('all')
    changesets=opts.get('changesets')
    ui.debug(_("input filename=%s ; AllChangesets=%s ; Changesets=%s \n") % (zipname, allchangesets, changesets))
    files=[]

    #work on the root repository
    runcmd(ui, repo.root, files, "0Root", repo['.'].rev(), ".", changesets, allchangesets)

    #do the same for each subrepository
    foreach(ui, repo, files, changesets, allchangesets)

    # open the zip file for writing, and write stuff to it
    ui.status("creating file: " + zipname + "\n\n")

    file = zipfile.ZipFile(zipname, "w" )
    for name in files:
        file.write(name, os.path.basename(name), zipfile.ZIP_DEFLATED)
    file.close()

    # open the file again, to see what's in it

    file = zipfile.ZipFile(zipname, "r")
    for info in file.infolist():
        ui.debug(info.filename + " " + str(info.date_time) + " " + str(info.file_size) + " " + str(info.compress_size) +"\n")
        #delete all the compressed .hg files
    os.remove(os.path.join(repo.root, info.filename)) 

    ui.status("\nOperation complete\n")


def foreach(ui, repo, files, changesets, allchangesets):
    ctx = repo['.']
    work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]

    while work:
        (depth, sub) = work.pop(0)

        if hasattr(subrepo, 'relpath'):
            relpath = subrepo.relpath(sub)
        else:
            relpath = subrepo.subrelpath(sub)

        rev=sub._repo[sub._state[1]].rev()

        ui.debug(str(rev) + " " + str(sub._repo[sub._state[1]].user()) + " " + str(sub._repo[sub._state[1]].date()) + "\n")

        if depth>1:
            raise Exception("No support for nested levels deeper than 1 yet.")

    runcmd(ui, repo.root, files, str(depth) + relpath, rev, relpath, changesets, allchangesets)

        if isinstance(sub, subrepo.hgsubrepo):
            rev = sub._state[1]
            ctx = sub._repo[rev]
            w = [(depth + 1, ctx.sub(subpath)) 
                 for subpath in sorted(ctx.substate)]
            work.extend(w)

def runcmd(ui, root, files, name, revision, path, changesets, allchangesets):
    files.append(root + "/" + name + ".hg")
    if (revision<=changesets) or allchangesets:
       cmd="hg bundle -a " + root + "/" + name + ".hg"
    else:
       cmd="hg bundle --base " + str(revision-changesets)+ " "  + root + "/" + name + ".hg"
    ui.note(_("Working on '%s' in %s\n") % (path, root))
    ui.debug( "command line: "+ cmd +"\n")
    util.system(cmd, 
        cwd=os.path.join(root, path),
        onerr=util.Abort,
        errprefix=_('terminated bundlesub in %s') % path)


cmdtable = {
    "bundlesb":
        (bundlesb,
         [('c', 'changesets', 10, _('the number of recent changesets to include in the bundle'), 'N'),
          ('a', 'all', None, _('include all changesets in the bundle')),],
         _('[-c|-a] FILE...'))

}

En andersom:

 """execute the UnBundle command in a repository and each subrepository
           for a file created with BundleSb"""

# unbundlesub.py - execute the UnBundle command in a repository and each subrepository
#
# Copyright 2012 Johan G.
#
# This software may be used and distributed according to the terms of
# the GNU General Public License version 2 or any later version.

import os
import zipfile
#import glob
from mercurial.i18n import _
from mercurial import extensions, subrepo, util

def unbundlesb(ui, repo, *args, **opts):
    """execute the UnBundle command in a repository and each subrepository
        for a file created with BundleSb

    Updates the current repository from a combined bundle (with hgs extention). 

    Use --verbose/-v to print more detailed information during the operation. 
    """
    ui.status("Starting unbundle operation\n")

    update = opts.get('update')
    file = os.path.splitext(' '.join(args))[0] + '.hgs'
    if (file==''):
       raise ValueError("FILE cannot be empty")

    ui.debug("input filename=" + file + "\n")
    zfile = zipfile.ZipFile(file, "r" )
    for info in zfile.infolist():
        ui.debug(info.filename + " " + str(info.date_time) + " " + str(info.file_size) + " " + str(info.compress_size) +"\n")
    zfile.extract(info,repo.root)
        runcmd(ui, repo.root, info.filename, update)
        #delete all the compressed .hg files
    os.remove(os.path.join(repo.root, info.filename)) 

    zfile.close()

    ui.status("\nOperation complete\n")


def runcmd(ui, root, name, update):
    level=name[0]
    rep=name[1:len(name)-3]
    ui.debug(_("Detected level=%s for repository %s \n") % (level, rep))
    cmd="hg unbundle "
    if (update): cmd= cmd + "-u "
    cmd= cmd + root + "\\" + name 
    ui.note(_("Working on '%s' in %s\n") % (rep, root))
    if (level == '1'):
        wd=os.path.join(root, rep)
    elif (level=='0'):
        wd=root
    else:
       raise Exception("Do not know what to do with a level >1")

    ui.debug(_("command line: %s in working directory %s\n") % (cmd, wd))

    util.system(cmd, 
            cwd=wd,
            onerr=util.Abort,
            errprefix=_('terminated unbundlesub in %s') % rep)


cmdtable = {
    "unbundlesb":
        (unbundlesb,
         [('u', 'update', None,
           _('update to new branch head if changesets were unbundled'))],
         _('[-u] FILE...'))
}
0
toegevoegd