Borrowing from "git pack-objects" manpage[1] we have: A packed archive is an efficient way to transfer a set of objects between two repositories as well as an access efficient archival format. In a packed archive, an object is either stored as a compressed whole or as a difference from some other object. The latter is often called a delta.
The packed archive format (.pack) is designed to be self-contained so that it can be unpacked without any further information. Therefore, each object that a delta depends upon must be present within the pack. A pack index file (.idx) is generated for fast, random access to the objects in the pack. Placing both the index file (.idx) and the packed archive (.pack) in the pack/ subdirectory [...] enables Git to read from the pack archive. As stated, they are self-contained and can encapsulate an entire chunk of development history starting at point A and ending at point B, which makes them ideal not just for transferring, but also for sharing that chunk of history between repositories with common ancestry. When you ask a server for something, it sends a single pack, because that is most efficient. So, using the kernel as an example, lets say we decide we want to use the 2005 git "epoch" as "A" and the v5.10 tag of a recent release as "B" to delineate an initial block of history. We can grab that chunk of history with a simple: git clone --bare --single-branch --branch v5.10 git://someserver/linux my-510-lib and we now have all the history up to and including v5.10 tag in a repo that we can use with further "clone --reference my-510-lib newstuff" as a static unchanging library of all those objects for "newstuff" to use. In making such a clone, Git stores the my-510-lib dir in the objects/info/alternates of "newstuff" and all the refs and tags carry forard into [packed]refs of "newstuff". Subsequent uses of the "newstuff" repo are only using the objects from "my-510-lib" and they are conveniently all stored in one pack, as there are no loose objects. In fact it is a waste of time even having git operations look for them. This means we can simply remove the alternates file and link the pack (and accompanying index file) into the pack dir of "newstuff". And by using symlinks with relative paths, we get a mirror friendly reference with no data download duplication. The "clone --reference" is simply used as a convenience tool to do 99% of the setup work. The linked in pack is "just a normal pack" to the consumer of the commit library. As such, we introduce a "packref" as a useful parallel addition to the more well known "altref". It is ideally suited to reference from static repositories containing a known block of commit history. Note that we don't limit ourselves to a single pack, so that a packref can itself be using another repo as its own packref and so on. Hence there is no arbitrary limit of a depth of 5 as there is with a reference using the more common alternates (i.e. "altref") method. This opens the door to insert an arbitrary number of split points between A and B to fragment large repos, if desired. An example that shows how the bulk of kernel history can be split in two, three or four chunks will be provided for recipes-kernel/linux subsequently. [1] https://git-scm.com/docs/git-pack-objects Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com> --- .../bitbake-user-manual-fetching.rst | 7 +++++ bitbake/lib/bb/fetch2/git.py | 31 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst index 12a68accc2c5..db1d108f4736 100644 --- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst +++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst @@ -453,6 +453,13 @@ This fetcher supports the following parameters: is responsible (via fetch dependency) for ensuring the reference is populated/cloned prior to being called on to act as a reference. +- *"packref":* Enables cloned ``git://`` URLs to use packs from the named + peer from the downloads dir as if they were their own packs of commit + history. Similar to ``altref`` above, but suited for bare static repos + for which no loose objects outside of packs will ever be present. + Recipe is responsible (via fetch dependency) for ensuring the reference + is populated/cloned prior to being called on to act as a reference. + Here are some example URLs: :: SRC_URI = "git://git.oe.handhelds.org/git/vip.git;tag=version-1" diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py index 3b0c068bc020..8aec12df2bf8 100644 --- a/bitbake/lib/bb/fetch2/git.py +++ b/bitbake/lib/bb/fetch2/git.py @@ -65,6 +65,14 @@ Supported SRC_URI options are: operations. Recipe is responsible (via fetch dependency) for ensuring the reference is populated/cloned prior to being called on to act as a reference. +- packref + Repository is to use packs from named peer from downloads dir by linking + them into objects/pack/ of the new repository as if they were their own + packs of commit history. Similar to altref above, but suited for bare + static repos for which no loose objects outside of packs will be present. + Recipe is responsible (via fetch dependency) for ensuring the reference + is populated/cloned prior to being called on to act as a reference. + - usehead For local git:// urls to use the current branch HEAD as the revision for use with AUTOREV. Implies nobranch. @@ -171,10 +179,15 @@ class Git(FetchMethod): ud.static = ud.parm.get("static","0") == "1" + ud.packref = ud.parm.get("packref","") + ud.altref = ud.parm.get("altref","") ud.dlname = ud.parm.get("dlname","") + if ud.packref and ud.altref: + raise bb.fetch2.ParameterError("Please pick only ONE reference style: alternates OR packs", ud.url) + # usehead implies nobranch ud.usehead = ud.parm.get("usehead","0") == "1" if ud.usehead: @@ -373,6 +386,14 @@ class Git(FetchMethod): static = self.get_git_config(ud, d, repo, "bitbake.static") return (static == "true") + def create_pack_links(self, refname, refdir, dstdir): + dstpkdir = os.path.join(dstdir, 'objects', 'pack') + refpkdir = os.path.join(refdir, 'objects', 'pack') + for item in os.listdir(refpkdir): + dst = os.path.join(dstpkdir, item) + src = os.path.join('..', '..', '..', refname, 'objects', 'pack', item) + os.symlink(src, dst) + def download(self, ud, d): """Fetch url""" @@ -388,7 +409,9 @@ class Git(FetchMethod): repourl = self._get_repo_url(ud) - refname = ud.altref + # Both style of reference are the same for initial clone operation. + # It is the post-clone absolute to relative path fixup that differs. + refname = ud.altref or ud.packref if refname: alts = os.path.join(ud.clonedir, 'objects', 'info', 'alternates') gitdir = d.getVar("GITDIR") or (d.getVar("DL_DIR") + "/git2") @@ -419,6 +442,12 @@ class Git(FetchMethod): if ud.static: runfetchcmd("%s config --bool --add bitbake.static 1" % ud.basecmd, d, workdir=ud.clonedir) + if ud.packref: + if not self.repo_is_static(ud, d, refdir): + raise bb.fetch2.FetchError("Pack reference '%s' is not marked as static content." % refname) + self.create_pack_links(refname, refdir, ud.clonedir) + os.remove(alts) + # Update the checkout if needed if self.clonedir_need_update(ud, d): if ud.altref: -- 2.25.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#9643): https://lists.yoctoproject.org/g/linux-yocto/message/9643 Mute This Topic: https://lists.yoctoproject.org/mt/81808165/21656 Group Owner: linux-yocto+ow...@lists.yoctoproject.org Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-