diff --git a/Makefile b/Makefile
index 5344d66..200c196 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,13 @@
include /usr/share/dpkg/pkg-info.mk
include /usr/share/dpkg/architecture.mk
+include defines.mk
PACKAGE=proxmox-offline-mirror
BUILDDIR ?= $(PACKAGE)-$(DEB_VERSION_UPSTREAM)
BUILDDIR_TMP ?= $(BUILDDIR).tmp
+SUBDIRS := docs
+
DEB=$(PACKAGE)_$(DEB_VERSION_UPSTREAM_REVISION)_$(DEB_BUILD_ARCH).deb
LIB_DEB=librust-$(PACKAGE)-dev_$(DEB_VERSION_UPSTREAM_REVISION)_$(DEB_BUILD_ARCH).deb
DBG_DEB=$(PACKAGE)-dbgsym_$(DEB_VERSION_UPSTREAM_REVISION)_$(DEB_BUILD_ARCH).deb
@@ -23,6 +26,10 @@ all: cargo-build $(SUBDIRS)
cargo-build:
cargo build $(CARGO_BUILD_ARGS)
+.PHONY: $(SUBDIRS)
+$(SUBDIRS):
+ $(MAKE) -C $@
+
.PHONY: build
build:
rm -rf $(BUILDDIR) $(BUILDDIR_TMP); mkdir $(BUILDDIR_TMP)
diff --git a/README b/README
deleted file mode 100644
index 7702ae4..0000000
--- a/README
+++ /dev/null
@@ -1,85 +0,0 @@
-proxmox-apt-mirror tool
-=======================
-
-This tool consists of two binaries, `proxmox-apt-mirror` (mirror tool to create
-and manage mirrors and media containing repositories) and `proxmox-apt-repo`
-(helper to use media on offline systems).
-
-There are two basic entity types available for configuration:
-- mirrors, consisting of upstream repository metadata and a local path where snapshots are stored
--- configured with `proxmox-apt-mirror config mirror ...`
--- used with `proxmox-apt-mirror mirror ...`
-- media, consisting of local mirrors and a path where mirrors are synced to
--- configured with `proxmox-apt-mirror config medium ...`
--- used with `proxmox-apt-mirror medium ...`
-
-and one internal one, a `pool` consisting of
-- a pool directory containing checksum files (e.g., `sha256/3dc7bc5f82cdcc4ea0f69dd30d5f6bb19e0ccc36f4a79c865eed0e7a370cd5e4`)
-- a base directory containing directories and hardlinks to checksum files inside the pool directory
-
-Adding a file consists of first adding the checksum file(s), then linking them
-under one or more paths. a garbage collect operation will iterate over all
-files in the base directory and remove those which are not (or no longer) a
-hardlink to any checksum files, and remove any checksum files which have no
-hardlinks outside of the pool checksum file directories.
-
-A default config path of `/etc/proxmox-apt-mirror.cfg` is used, but is
-overridable on a per command basis (for example, to allow operation as non-root
-user).
-
-Setting up a mirror
-===================
-
-First either run the `setup` wizard (`proxmox-apt-mirror setup`), or the
-`config mirror add` command. For example, to add a mirror entry for the Debian
-Bullseye security repository, the following command can be used:
-
- proxmox-apt-mirror config mirror add \
- --id debian-bullseye-security \
- --architectures amd64 \
- --architectures all \
- --repository 'deb http://deb.debian.org/debian-security bullseye-security main contrib non-free' \
- --key-path /etc/apt/trusted.gpg.d/debian-archive-bullseye-security-automatic.gpg \
- --sync true \
- --verify true \
- --base-dir /path/to/mirror/dir/debian-bullseye-security \
- --pool-dir /path/to/mirror/dir/debian-bullseye-security/.pool
-
-Syncing a mirror
-================
-
-To create the first (and subsequent) snapshots, the following command can be used:
-
- proxmox-apt-mirror mirror snapshot create --id debian-bullseye-security
-
-Setting up a medium
-===================
-
-Either run the `setup` wizard again, or use the `config medium add` command.
-For example, to define a new medium containing the
-`proxmox-ve-bullseye-no-subscription` and `debian-bullseye` mirrors, run the
-following command:
-
- proxmox-apt-mirror config medium add \
- --id pve-bullseye \
- --mirrors proxmox-ve-bullseye-no-subscription \
- --mirrors debian-bullseye \
- --sync true \
- --verify true \
- --mountpoint /path/where/medium/is/mounted
-
-Syncing a medium
-================
-
-To sync the local mirrors to a medium, the following command can be used:
-
- proxmox-apt-mirror medium sync --id pve-bullseye
-
-Using a medium
-==============
-
-After syncing a medium, unmount it and make it accessible on the (offline)
-target system. You can now either manually point apt at the synced snapshots,
-or run `proxmox-apt-repo setup` to generate a sources.list.d snippet referecing
-selected mirrors and snapshots. Don't forget to remove the snippet again after
-the upgrade is done.
diff --git a/debian/rules b/debian/rules
new file mode 100644
index 0000000..879a659
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,13 @@
+#!/usr/bin/make -f
+
+export BUILD_MODE=release-deb
+%:
+ dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+ # skip for now to avoid additional debug builds - no tests anyway
+ # dh_auto_test -- test --all
+
+override_dh_auto_install:
+ dh_auto_install
+ DESTDIR=../debian/proxmox-offline-mirror make -C docs install
diff --git a/defines.mk b/defines.mk
new file mode 100644
index 0000000..ebccd2b
--- /dev/null
+++ b/defines.mk
@@ -0,0 +1,14 @@
+PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+SBINDIR = $(PREFIX)/sbin
+LIBDIR = $(PREFIX)/lib
+LIBEXECDIR = $(LIBDIR)
+DATAROOTDIR = $(PREFIX)/share
+MAN1DIR = $(PREFIX)/share/man/man1
+MAN5DIR = $(PREFIX)/share/man/man5
+DOCDIR = $(PREFIX)/share/doc/proxmox-offline-mirror
+SYSCONFDIR = /etc
+ZSH_COMPL_DEST = $(PREFIX)/share/zsh/vendor-completions
+
+# For local overrides
+-include local.mak
diff --git a/docs/GFDL.rst b/docs/GFDL.rst
new file mode 100644
index 0000000..67a6d11
--- /dev/null
+++ b/docs/GFDL.rst
@@ -0,0 +1,422 @@
+GNU Free Documentation License
+==============================
+
+Version 1.3, 3 November 2008
+
+
+Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+
+Everyone is permitted to copy and distribute verbatim copies of this
+ license document, but changing it is not allowed.
+
+0. PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document "free" in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of "copyleft", which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+
+1. APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The "Document", below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as "you". You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A "Modified Version" of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A "Secondary Section" is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject. (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.) The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The "Invariant Sections" are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
+
+The "Cover Texts" are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A "Transparent" copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters. A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not "Transparent" is called "Opaque".
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML, PostScript or PDF designed for human modification. Examples of
+transparent image formats include PNG, XCF and JPG. Opaque formats
+include proprietary formats that can be read and edited only by
+proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML, PostScript or PDF produced by some word
+processors for output purposes only.
+
+The "Title Page" means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page. For works in
+formats which do not have any title page as such, "Title Page" means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+The "publisher" means any person or entity that distributes copies of
+the Document to the public.
+
+A section "Entitled XYZ" means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as "Acknowledgements",
+"Dedications", "Endorsements", or "History".) To "Preserve the Title"
+of such a section when you modify the Document means that it remains a
+section "Entitled XYZ" according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+2. VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no
+other conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+
+3. COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover. Both covers must also clearly and legibly identify
+you as the publisher of these copies. The front cover must present
+the full title with all words of the title equally prominent and
+visible. You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to
+give them a chance to provide you with an updated version of the
+Document.
+
+
+4. MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it. In addition, you must do these things in the Modified Version:
+
+A. Use in the Title Page (and on the covers, if any) a title distinct
+ from that of the Document, and from those of previous versions
+ (which should, if there were any, be listed in the History section
+ of the Document). You may use the same title as a previous version
+ if the original publisher of that version gives permission.
+B. List on the Title Page, as authors, one or more persons or entities
+ responsible for authorship of the modifications in the Modified
+ Version, together with at least five of the principal authors of the
+ Document (all of its principal authors, if it has fewer than five),
+ unless they release you from this requirement.
+C. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+D. Preserve all the copyright notices of the Document.
+E. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+F. Include, immediately after the copyright notices, a license notice
+ giving the public permission to use the Modified Version under the
+ terms of this License, in the form shown in the Addendum below.
+G. Preserve in that license notice the full lists of Invariant Sections
+ and required Cover Texts given in the Document's license notice.
+H. Include an unaltered copy of this License.
+I. Preserve the section Entitled "History", Preserve its Title, and add
+ to it an item stating at least the title, year, new authors, and
+ publisher of the Modified Version as given on the Title Page. If
+ there is no section Entitled "History" in the Document, create one
+ stating the title, year, authors, and publisher of the Document as
+ given on its Title Page, then add an item describing the Modified
+ Version as stated in the previous sentence.
+J. Preserve the network location, if any, given in the Document for
+ public access to a Transparent copy of the Document, and likewise
+ the network locations given in the Document for previous versions
+ it was based on. These may be placed in the "History" section.
+ You may omit a network location for a work that was published at
+ least four years before the Document itself, or if the original
+ publisher of the version it refers to gives permission.
+K. For any section Entitled "Acknowledgements" or "Dedications",
+ Preserve the Title of the section, and preserve in the section all
+ the substance and tone of each of the contributor acknowledgements
+ and/or dedications given therein.
+L. Preserve all the Invariant Sections of the Document,
+ unaltered in their text and in their titles. Section numbers
+ or the equivalent are not considered part of the section titles.
+M. Delete any section Entitled "Endorsements". Such a section
+ may not be included in the Modified Version.
+N. Do not retitle any existing section to be Entitled "Endorsements"
+ or to conflict in title with any Invariant Section.
+O. Preserve any Warranty Disclaimers.
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled "Endorsements", provided it contains
+nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity. If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+
+5. COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled "History"
+in the various original documents, forming one section Entitled
+"History"; likewise combine any sections Entitled "Acknowledgements",
+and any sections Entitled "Dedications". You must delete all sections
+Entitled "Endorsements".
+
+
+6. COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other
+documents released under this License, and replace the individual
+copies of this License in the various documents with a single copy
+that is included in the collection, provided that you follow the rules
+of this License for verbatim copying of each of the documents in all
+other respects.
+
+You may extract a single document from such a collection, and
+distribute it individually under this License, provided you insert a
+copy of this License into the extracted document, and follow this
+License in all other respects regarding verbatim copying of that
+document.
+
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an "aggregate" if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+
+8. TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled "Acknowledgements",
+"Dedications", or "History", the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+
+9. TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, or distribute it is void, and
+will automatically terminate your rights under this License.
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, receipt of a copy of some or all of the same material does
+not give you any rights to use it.
+
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions of the
+GNU Free Documentation License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in
+detail to address new problems or concerns. See
+https://www.gnu.org/licenses/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation. If the Document
+specifies that a proxy can decide which future versions of this
+License can be used, that proxy's public statement of acceptance of a
+version permanently authorizes you to choose that version for the
+Document.
+
+11. RELICENSING
+
+"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
+World Wide Web server that publishes copyrightable works and also
+provides prominent facilities for anybody to edit those works. A
+public wiki that anybody can edit is an example of such a server. A
+"Massive Multiauthor Collaboration" (or "MMC") contained in the site
+means any set of copyrightable works thus published on the MMC site.
+
+"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
+license published by Creative Commons Corporation, a not-for-profit
+corporation with a principal place of business in San Francisco,
+California, as well as future copyleft versions of that license
+published by that same organization.
+
+"Incorporate" means to publish or republish a Document, in whole or in
+part, as part of another Document.
+
+An MMC is "eligible for relicensing" if it is licensed under this
+License, and if all works that were first published under this License
+somewhere other than this MMC, and subsequently incorporated in whole or
+in part into the MMC, (1) had no cover texts or invariant sections, and
+(2) were thus incorporated prior to November 1, 2008.
+
+The operator of an MMC Site may republish an MMC contained in the site
+under CC-BY-SA on the same site at any time before August 1, 2009,
+provided the MMC is eligible for relicensing.
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..05b9067
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,94 @@
+include ../defines.mk
+
+GENERATED_SYNOPSIS := \
+ proxmox-offline-mirror/synopsis.rst \
+ proxmox-apt-repo/synopsis.rst \
+ config/mirror/config.rst
+
+MAN1_PAGES := \
+ proxmox-offline-mirror.1 \
+ proxmox-apt-repo.1
+
+MAN5_PAGES := \
+ mirror.cfg.5
+
+# Sphinx documentation setup
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+BUILDDIR = output
+
+ifeq ($(BUILD_MODE), release)
+COMPILEDIR := ../target/release
+SPHINXOPTS += -t release
+else ifeq ($(BUILD_MODE), release-deb)
+COMPILEDIR := ../target/$(DEB_TARGET_GNU_CPU)-unknown-$(DEB_TARGET_GNU_SYSTEM)/release
+SPHINXOPTS += -t release
+else
+COMPILEDIR := ../target/debug
+SPHINXOPTS += -t devbuild
+endif
+
+# Sphinx internal variables.
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(SPHINXOPTS) .
+
+all: ${MAN1_PAGES} ${MAN5_PAGES}
+
+config/%/config.rst: ${COMPILEDIR}/docgen
+ ${COMPILEDIR}/docgen $*.cfg >$@
+
+%/synopsis.rst: ${COMPILEDIR}/%
+ $< printdoc > $@
+
+${MAN1_PAGES} ${MAN5_PAGES}: man-pages
+
+.PHONY: man-pages
+man-pages: ${GENERATED_SYNOPSIS}
+ ${SPHINXBUILD} ${SPHINXOPTS} -b man ./ ${BUILDDIR}/man
+
+.PHONY: html
+html: ${GENERATED_SYNOPSIS} images/proxmox-logo.svg custom.css conf.py ${PRUNE_SIMULATOR_FILES} ${LTO_BARCODE_FILES} ${API_VIEWER_SOURCES}
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ install -m 0644 custom.js custom.css images/proxmox-logo.svg $(BUILDDIR)/html/_static/
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: latexpdf
+latexpdf: ${GENERATED_SYNOPSIS}
+ @echo "Requires python3-sphinx, texlive-xetex, xindy and texlive-fonts-extra"
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through xelatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: epub3
+epub3: ${GENERATED_SYNOPSIS}
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ @echo
+ @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+clean:
+ rm -r -f *~ *.1 ${BUILDDIR} ${GENERATED_SYNOPSIS}
+
+install_manual_pages: man-pages
+ install -dm755 $(DESTDIR)$(MAN1DIR)
+ for i in ${MAN1_PAGES}; do install -m755 ${BUILDDIR}/man/$$i $(DESTDIR)$(MAN1DIR)/ ; done
+ install -dm755 $(DESTDIR)$(MAN5DIR)
+ for i in ${MAN5_PAGES}; do install -m755 ${BUILDDIR}/man/$$i $(DESTDIR)$(MAN5DIR)/ ; done
+
+install_html: html
+ install -dm755 $(DESTDIR)$(DOCDIR)
+ rsync -a ${BUILDDIR}/html $(DESTDIR)$(DOCDIR)
+
+install_pdf: latexpdf
+ install -dm755 $(DESTDIR)$(DOCDIR)
+ install -m 0644 output/latex/ProxmoxOfflineMirror.pdf $(DESTDIR)$(DOCDIR)/proxmox-offline-mirror.pdf
+
+ifneq ($(filter nodoc,$(DEB_BUILD_PROFILES)),)
+
+install: install_manual_pages
+
+else
+
+install: install_manual_pages install_html install_pdf
+
+endif
\ No newline at end of file
diff --git a/docs/_ext/__pycache__/proxmox-scanrefs.cpython-39.pyc b/docs/_ext/__pycache__/proxmox-scanrefs.cpython-39.pyc
new file mode 100644
index 0000000..d6ccc52
Binary files /dev/null and b/docs/_ext/__pycache__/proxmox-scanrefs.cpython-39.pyc differ
diff --git a/docs/_ext/proxmox-scanrefs.py b/docs/_ext/proxmox-scanrefs.py
new file mode 100644
index 0000000..0d62656
--- /dev/null
+++ b/docs/_ext/proxmox-scanrefs.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+
+# debugging stuff
+from pprint import pprint
+
+from typing import cast
+
+import json
+import re
+
+import os
+import io
+from docutils import nodes
+
+from sphinx.builders import Builder
+from sphinx.util import logging
+
+logger = logging.getLogger(__name__)
+
+# refs are added in the following manner before the title of a section (note underscore and newline before title):
+# .. _my-label:
+#
+# Section to ref
+# --------------
+#
+#
+# then referred to like (note missing underscore):
+# "see :ref:`my-label`"
+#
+# the benefit of using this is if a label is explicitly set for a section,
+# we can refer to it with this anchor #my-label in the html,
+# even if the section name changes.
+#
+# see https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-ref
+
+def scan_extjs_files(wwwdir="../www"): # a bit rough i know, but we can optimize later
+ js_files = []
+ used_anchors = []
+ logger.info("scanning extjs files for onlineHelp definitions")
+ for root, dirs, files in os.walk("{}".format(wwwdir)):
+ #print(root, dirs, files)
+ for filename in files:
+ if filename.endswith('.js'):
+ js_files.append(os.path.join(root, filename))
+ for js_file in js_files:
+ fd = open(js_file).read()
+ allmatch = re.findall("(?:onlineHelp:|get_help_tool\s*\()\s*[\'\"](.*?)[\'\"]", fd, re.M)
+ for match in allmatch:
+ anchor = match
+ anchor = re.sub('_', '-', anchor) # normalize labels
+ logger.info("found onlineHelp: {} in {}".format(anchor, js_file))
+ used_anchors.append(anchor)
+
+ return used_anchors
+
+
+def setup(app):
+ logger.info('Mapping reference labels...')
+ app.add_builder(ReflabelMapper)
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
+
+class ReflabelMapper(Builder):
+ name = 'proxmox-scanrefs'
+
+ def init(self):
+ self.docnames = []
+ self.env.online_help = {}
+ self.env.online_help['pbs_documentation_index'] = {
+ 'link': '/docs/index.html',
+ 'title': 'Proxmox Backup Server Documentation Index',
+ }
+ # Disabled until we find a sensible way to scan proxmox-widget-toolkit
+ # as well
+ #self.env.used_anchors = scan_extjs_files()
+
+ if not os.path.isdir(self.outdir):
+ os.mkdir(self.outdir)
+
+ self.output_filename = os.path.join(self.outdir, 'OnlineHelpInfo.js')
+ self.output = io.open(self.output_filename, 'w', encoding='UTF-8')
+
+ def write_doc(self, docname, doctree):
+ for node in doctree.traverse(nodes.section):
+ #pprint(vars(node))
+
+ if hasattr(node, 'expect_referenced_by_id') and len(node['ids']) > 1: # explicit labels
+ filename = self.env.doc2path(docname)
+ filename_html = re.sub('.rst', '.html', filename)
+
+ # node['ids'][0] contains a normalized version of the
+ # headline. If the ref and headline are the same
+ # (normalized) sphinx will set the node['ids'][1] to a
+ # generic id in the format `idX` where X is numeric. If the
+ # ref and headline are not the same, the ref name will be
+ # stored in node['ids'][1]
+ if re.match('^id[0-9]*$', node['ids'][1]):
+ labelid = node['ids'][0]
+ else:
+ labelid = node['ids'][1]
+
+ title = cast(nodes.title, node[0])
+ logger.info('traversing section {}'.format(title.astext()))
+ ref_name = getattr(title, 'rawsource', title.astext())
+
+ if (ref_name[:7] == ':term:`'):
+ ref_name = ref_name[7:-1]
+
+ self.env.online_help[labelid] = {'link': '', 'title': ''}
+ self.env.online_help[labelid]['link'] = "/docs/" + os.path.basename(filename_html) + "#{}".format(labelid)
+ self.env.online_help[labelid]['title'] = ref_name
+
+ return
+
+
+ def get_outdated_docs(self):
+ return 'all documents'
+
+ def prepare_writing(self, docnames):
+ return
+
+ def get_target_uri(self, docname, typ=None):
+ return ''
+
+ def validate_anchors(self):
+ #pprint(self.env.online_help)
+ to_remove = []
+
+ # Disabled until we find a sensible way to scan proxmox-widget-toolkit
+ # as well
+ #for anchor in self.env.used_anchors:
+ # if anchor not in self.env.online_help:
+ # logger.info("[-] anchor {} is missing from onlinehelp!".format(anchor))
+ #for anchor in self.env.online_help:
+ # if anchor not in self.env.used_anchors and anchor != 'pbs_documentation_index':
+ # logger.info("[*] anchor {} not used! deleting...".format(anchor))
+ # to_remove.append(anchor)
+ #for anchor in to_remove:
+ # self.env.online_help.pop(anchor, None)
+ return
+
+ def finish(self):
+ # generate OnlineHelpInfo.js output
+ self.validate_anchors()
+
+ self.output.write("const proxmoxOnlineHelpInfo = ")
+ self.output.write(json.dumps(self.env.online_help, indent=2))
+ self.output.write(";\n")
+ self.output.close()
+ return
diff --git a/docs/_templates/index-sidebar.html b/docs/_templates/index-sidebar.html
new file mode 100644
index 0000000..45e0635
--- /dev/null
+++ b/docs/_templates/index-sidebar.html
@@ -0,0 +1,11 @@
+
+
diff --git a/docs/command-syntax.rst b/docs/command-syntax.rst
new file mode 100644
index 0000000..7fefc0b
--- /dev/null
+++ b/docs/command-syntax.rst
@@ -0,0 +1,13 @@
+Command Syntax
+==============
+
+``proxmox-offline-mirror``
+--------------------------
+
+.. include:: proxmox-offline-mirror/synopsis.rst
+
+
+``proxmox-apt-repo``
+--------------------
+
+.. include:: proxmox-apt-repo/synopsis.rst
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..e1d9f3c
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,475 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Proxmox Backup documentation build configuration file, originally
+# created by sphinx-quickstart on Tue Feb 26 16:54:35 2019.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+# custom extensions
+sys.path.append(os.path.abspath("./_ext"))
+
+# -- Implement custom formatter for code-blocks ---------------------------
+#
+# * use smaller font
+# * avoid space between lines to nicely format utf8 tables
+
+from sphinx.highlighting import PygmentsBridge
+from pygments.formatters.latex import LatexFormatter
+
+class CustomLatexFormatter(LatexFormatter):
+ def __init__(self, **options):
+ super(CustomLatexFormatter, self).__init__(**options)
+ self.verboptions = r"formatcom=\footnotesize\relax\let\strut\empty"
+
+PygmentsBridge.latex_formatter = CustomLatexFormatter
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+
+extensions = ["sphinx.ext.graphviz", 'sphinx.ext.mathjax', "sphinx.ext.todo", "proxmox-scanrefs"]
+
+todo_link_only = True
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'Proxmox Offline Mirror'
+copyright = '2022, Proxmox Server Solutions GmbH'
+author = 'Proxmox Support Team'
+
+# The version info for the project you're documenting, acts as a replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+vstr = lambda s: '' if s is None else str(s)
+
+version = vstr(os.getenv('DEB_VERSION_UPSTREAM'))
+# The full version, including alpha/beta/rc tags.
+release = vstr(os.getenv('DEB_VERSION'))
+
+epilog_file = open('epilog.rst', 'r')
+rst_epilog = epilog_file.read()
+rst_epilog += f"\n.. |VERSION| replace:: {version}"
+rst_epilog += f"\n.. |pom-copyright| replace:: Copyright (C) {copyright}"
+
+man_pages = [
+ # CLI
+ ('proxmox-offline-mirror/man1', 'proxmox-offline-mirror', 'Command line tool for Backup and Restore', [author], 1),
+ ('proxmox-apt-repo/man1', 'proxmox-apt-repo', 'Command line tool to manage and configure the backup server.', [author], 1),
+ # configs
+ ('config/mirror/man5', 'mirror.cfg', 'Mirror Configuration', [author], 5),
+]
+
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+#
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%A, %d %B %Y'
+
+suppress_warnings = [ 'toc.excluded' ]
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = [
+ '_build', 'Thumbs.db', '.DS_Store',
+ 'epilog.rst',
+ 'pbs-copyright.rst',
+]
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = not tags.has('release')
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#
+html_theme_options = {
+ 'fixed_sidebar': True,
+ 'sidebar_includehidden': False,
+ 'sidebar_collapse': False,
+ 'globaltoc_collapse': False,
+ 'show_relbar_bottom': True,
+ 'show_powered_by': False,
+
+ 'extra_nav_links': {
+ 'Proxmox Homepage': 'https://proxmox.com',
+ 'PDF': 'proxmox-offline-mirror.pdf',
+ },
+
+ 'sidebar_width': '320px',
+ 'page_width': '1320px',
+ # font styles
+ 'head_font_family': 'Lato, sans-serif',
+ 'caption_font_family': 'Lato, sans-serif',
+ 'caption_font_size': '20px',
+ 'font_family': 'Open Sans, sans-serif',
+}
+
+# Alabaster theme recommends setting this fixed.
+# If you switch theme this needs to removed, probably.
+html_sidebars = {
+ '**': [
+ 'sidebar-header.html',
+ 'searchbox.html',
+ 'navigation.html',
+ 'relations.html',
+ ],
+
+ 'index': [
+ 'sidebar-header.html',
+ 'searchbox.html',
+ 'index-sidebar.html',
+ ]
+}
+
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents.
+# " v documentation" by default.
+#
+# html_title = 'Proxmox Backup v1.0-1'
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#
+#html_logo = 'images/proxmox-logo.svg' # replaced by html_theme_options.logo
+
+# The name of an image file (relative to this directory) to use as a favicon of
+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#
+html_favicon = 'images/favicon.ico'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+html_js_files = [
+ 'custom.js',
+]
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#
+# html_extra_path = []
+
+# If not None, a 'Last updated on:' timestamp is inserted at every page
+# bottom, using the given strftime format.
+# The empty string is equivalent to '%b %d, %Y'.
+#
+# html_last_updated_fmt = None
+
+# We need to disable smatquotes, else Option Lists do not display long options
+smartquotes = False
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+#
+# html_domain_indices = True
+
+# If false, no index is generated.
+#
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
+#
+# html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# 'ja' uses this config value.
+# 'zh' user can custom change `jieba` dictionary path.
+#
+# html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#
+# html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ProxmoxOfflineMirrordoc'
+
+# use local mathjax package, symlink comes from debian/proxmox-backup-docs.links
+mathjax_path = "mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_engine = 'xelatex'
+
+latex_elements = {
+ 'fontenc': '\\usepackage{fontspec}',
+
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ 'papersize': 'a4paper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ 'pointsize': '10pt',
+
+ 'fontpkg': r'''
+\setmainfont{Open Sans}
+\setsansfont{Lato}
+\setmonofont{DejaVu Sans Mono}
+''',
+
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'ProxmoxOfflineMirror.tex', 'Proxmox Offline Mirror Documentation',
+ 'Proxmox Support Team', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#
+#
+# Note: newer sphinx 1.6 should be able to convert .svg to .png
+# automatically using sphinx.ext.imgconverter
+latex_logo = "images/proxmox-logo.png"
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+#
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#
+# latex_appendices = []
+
+# It false, will not define \strong, \code, itleref, \crossref ... but only
+# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
+# packages.
+#
+# latex_keep_old_macro_names = True
+
+# If false, no module index is generated.
+#
+# latex_domain_indices = True
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+# epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not
+# optimized for small screen space, using the same theme for HTML and epub
+# output is usually not wise. This defaults to 'epub', a theme designed to save
+# visual space.
+#
+# epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#
+# epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+# epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#
+# epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#
+# epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#
+# epub_pre_files = []
+
+# HTML files that should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#
+# epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#
+# epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#
+# epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#
+# epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#
+# epub_fix_images = False
+
+# Scale large images.
+#
+# epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#
+# epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#
+# epub_use_index = True
diff --git a/docs/config/mirror/man5.rst b/docs/config/mirror/man5.rst
new file mode 100644
index 0000000..913b40c
--- /dev/null
+++ b/docs/config/mirror/man5.rst
@@ -0,0 +1,16 @@
+==========
+mirror.cfg
+==========
+
+Description
+===========
+
+The file /etc/proxmox-offline-mirror.cfg is a configuration file for Proxmox
+Offline Mirror. It contains definitions for mirrors, media and subscription keys.
+
+Options
+=======
+
+.. include:: config.rst
+
+.. include:: ../../pom-copyright.rst
diff --git a/docs/configuration-files.rst b/docs/configuration-files.rst
new file mode 100644
index 0000000..fe8cfb4
--- /dev/null
+++ b/docs/configuration-files.rst
@@ -0,0 +1,14 @@
+Configuration Files
+===================
+
+The Proxmox Offline Mirror configuration file is stored at ``/etc/proxmox-offline-mirror.cfg`` by default. Its location can be overriden for any given command using the `--config` parameter.
+
+
+``mirror.cfg``
+~~~~~~~~~~~~~~
+
+
+Options
+^^^^^^^
+
+.. include:: config/mirror/config.rst
diff --git a/docs/custom.css b/docs/custom.css
new file mode 100644
index 0000000..fe8b795
--- /dev/null
+++ b/docs/custom.css
@@ -0,0 +1,88 @@
+div.sphinxsidebar {
+ height: calc(100% - 20px);
+ overflow: auto;
+}
+
+h1.logo-name {
+ font-size: 24px;
+}
+
+div.body img {
+ width: 250px;
+}
+pre {
+ padding: 5px 10px;
+}
+
+div.topic {
+ background-color: #FAFAFA;
+}
+
+li a.current {
+ font-weight: bold;
+ border-bottom: 1px solid #000;
+}
+ul li.toctree-l1 {
+ margin-top: 0.5em;
+}
+ul li.toctree-l1 > a {
+ color: #000;
+}
+
+div.sphinxsidebar ul {
+ color: #444;
+}
+div.sphinxsidebar ul ul {
+ list-style: circle;
+}
+div.sphinxsidebar ul ul ul {
+ list-style: square;
+}
+
+div.sphinxsidebar ul a code {
+ font-weight: normal;
+}
+div.sphinxsidebar ul ul a {
+ border-bottom: 1px dotted #CCC;
+}
+
+div.sphinxsidebar form.search {
+ margin-bottom: 5px;
+}
+
+div.sphinxsidebar h3 {
+ width: 100%;
+}
+
+div.sphinxsidebar h1.logo-name {
+ display: none;
+}
+
+div.document, div.footer {
+ width: min(100%, 1320px);
+}
+
+@media screen and (max-width: 875px) {
+ div.sphinxsidebar p.logo {
+ display: initial;
+ }
+ div.sphinxsidebar h1.logo-name {
+ display: block;
+ }
+ div.sphinxsidebar span {
+ color: #EEE;
+ }
+ .sphinxsidebar ul li.toctree-l1 > a, div.sphinxsidebar a {
+ color: #FFF;
+ }
+ div.sphinxsidebar {
+ background-color: #555;
+ }
+ div.body {
+ min-width: 300px;
+ }
+ div.footer {
+ display: block;
+ margin: 15px auto 0px auto;
+ }
+}
diff --git a/docs/custom.js b/docs/custom.js
new file mode 100644
index 0000000..7964b2c
--- /dev/null
+++ b/docs/custom.js
@@ -0,0 +1,7 @@
+window.addEventListener('DOMContentLoaded', (event) => {
+ let activeSection = document.querySelector("a.current");
+ if (activeSection) {
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
+ activeSection.scrollIntoView({ block: 'center' });
+ }
+});
diff --git a/docs/epilog.rst b/docs/epilog.rst
new file mode 100644
index 0000000..b5da481
--- /dev/null
+++ b/docs/epilog.rst
@@ -0,0 +1,19 @@
+.. Epilog (included at top of each file)
+
+ We use this file to define external links and common replacement
+ patterns.
+
+.. |WEBSITE| replace:: https://www.proxmox.com
+.. |DOWNLOADS| replace:: https://www.proxmox.com/downloads
+
+.. _Proxmox: https://www.proxmox.com
+.. _Proxmox Community Forum: https://forum.proxmox.com
+.. _Proxmox Virtual Environment: https://www.proxmox.com/proxmox-ve
+.. _Proxmox Backup: https://pbs.proxmox.com/wiki/index.php/Main_Page
+.. _PVE Development List: https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
+.. _reStructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html
+.. _Rust: https://www.rust-lang.org/
+.. _SHA-256: https://en.wikipedia.org/wiki/SHA-2
+
+.. _AGPL3: https://www.gnu.org/licenses/agpl-3.0.en.html
+.. _Debian: https://www.debian.org
diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico
new file mode 100755
index 0000000..ba0c9af
Binary files /dev/null and b/docs/images/favicon.ico differ
diff --git a/docs/images/proxmox-logo.png b/docs/images/proxmox-logo.png
new file mode 100644
index 0000000..659793a
Binary files /dev/null and b/docs/images/proxmox-logo.png differ
diff --git a/docs/images/proxmox-logo.svg b/docs/images/proxmox-logo.svg
new file mode 100644
index 0000000..bc5d22a
--- /dev/null
+++ b/docs/images/proxmox-logo.svg
@@ -0,0 +1,243 @@
+
+
+
+
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..9284f8b
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,47 @@
+.. Proxmox Backup documentation master file
+
+Welcome to the Proxmox Offline Mirror documentation!
+====================================================
+| |pom-copyright|
+| Version |version| -- |today|
+
+Permission is granted to copy, distribute and/or modify this document under the
+terms of the GNU Free Documentation License, Version 1.3 or any later version
+published by the Free Software Foundation; with no Invariant Sections, no
+Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included
+in the section entitled "GNU Free Documentation License".
+
+
+.. only:: html
+
+ A `PDF` version of the documentation is `also available here <./proxmox-offline-mirror.pdf>`_
+
+.. toctree::
+ :maxdepth: 3
+ :caption: Table of Contents
+
+ introduction.rst
+
+.. raw:: latex
+
+ \appendix
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Appendix
+
+ command-syntax.rst
+ configuration-files.rst
+ GFDL.rst
+
+.. only:: html and devbuild
+
+ .. toctree::
+ :maxdepth: 2
+ :hidden:
+ :caption: Developer Appendix
+
+ todos.rst
+
+
+.. # * :ref:`genindex`
diff --git a/docs/introduction.rst b/docs/introduction.rst
new file mode 100644
index 0000000..8472ed9
--- /dev/null
+++ b/docs/introduction.rst
@@ -0,0 +1,149 @@
+Introduction
+============
+
+What is Proxmox Offline Mirror?
+-------------------------------
+
+This tool consists of two binaries, `proxmox-offline-mirror` (mirror tool to create
+and manage mirrors and media containing repositories) and `proxmox-apt-repo`
+(helper to use media on offline systems).
+
+There are two basic entity types available for configuration:
+- mirrors, consisting of upstream repository metadata and a local path where snapshots are stored
+-- configured with `proxmox-offline-mirror config mirror ...`
+-- used with `proxmox-offline-mirror mirror ...`
+- media, consisting of local mirrors and a path where mirrors are synced to
+-- configured with `proxmox-offline-mirror config medium ...`
+-- used with `proxmox-offline-mirror medium ...`
+
+and one internal one, a `pool` consisting of
+- a pool directory containing checksum files (e.g., `sha256/3dc7bc5f82cdcc4ea0f69dd30d5f6bb19e0ccc36f4a79c865eed0e7a370cd5e4`)
+- a base directory containing directories and hardlinks to checksum files inside the pool directory
+
+Adding a file consists of first adding the checksum file(s), then linking them
+under one or more paths. a garbage collect operation will iterate over all
+files in the base directory and remove those which are not (or no longer) a
+hardlink to any checksum files, and remove any checksum files which have no
+hardlinks outside of the pool checksum file directories.
+
+A default config path of `/etc/proxmox-offline-mirror.cfg` is used, but is
+overridable on a per command basis (for example, to allow operation as non-root
+user).
+
+Setting up a mirror
+-------------------
+
+First either run the `setup` wizard (`proxmox-offline-mirror setup`), or the
+`config mirror add` command. For example, to add a mirror entry for the Debian
+Bullseye security repository, the following command can be used:
+
+ proxmox-offline-mirror config mirror add \
+ --id debian-bullseye-security \
+ --architectures amd64 \
+ --architectures all \
+ --repository 'deb http://deb.debian.org/debian-security bullseye-security main contrib non-free' \
+ --key-path /etc/apt/trusted.gpg.d/debian-archive-bullseye-security-automatic.gpg \
+ --sync true \
+ --verify true \
+ --base-dir /path/to/mirror/dir/debian-bullseye-security \
+ --pool-dir /path/to/mirror/dir/debian-bullseye-security/.pool
+
+Syncing a mirror
+----------------
+
+To create the first (and subsequent) snapshots, the following command can be used:
+
+ proxmox-offline-mirror mirror snapshot create --id debian-bullseye-security
+
+Setting up a medium
+-------------------
+
+Either run the `setup` wizard again, or use the `config medium add` command.
+For example, to define a new medium containing the
+`proxmox-ve-bullseye-no-subscription` and `debian-bullseye` mirrors, run the
+following command:
+
+ proxmox-offline-mirror config medium add \
+ --id pve-bullseye \
+ --mirrors proxmox-ve-bullseye-no-subscription \
+ --mirrors debian-bullseye \
+ --sync true \
+ --verify true \
+ --mountpoint /path/where/medium/is/mounted
+
+Syncing a medium
+----------------
+
+To sync the local mirrors to a medium, the following command can be used:
+
+ proxmox-offline-mirror medium sync --id pve-bullseye
+
+Using a medium
+--------------
+
+After syncing a medium, unmount it and make it accessible on the (offline)
+target system. You can now either manually point apt at the synced snapshots,
+or run `proxmox-apt-repo setup` to generate a sources.list.d snippet referecing
+selected mirrors and snapshots. Don't forget to remove the snippet again after
+the upgrade is done.
+
+
+.. _get_help:
+
+Getting Help
+------------
+
+.. _get_help_enterprise_support:
+
+Enterprise Support
+~~~~~~~~~~~~~~~~~~
+
+Users with a `Proxmox Offline Mirror Basic, Standard or Premium Subscription Plan
+`_ have access to the
+`Proxmox Customer Portal `_. The customer portal
+provides support with guaranteed response times from the Proxmox developers.
+For more information or for volume discounts, please contact office@proxmox.com.
+
+Community Support Forum
+~~~~~~~~~~~~~~~~~~~~~~~
+
+We always encourage our users to discuss and share their knowledge using the
+`Proxmox Community Forum`_. The forum is moderated by the Proxmox support team.
+The large user base is spread out all over the world. Needless to say that such
+a large forum is a great place to get information.
+
+Mailing Lists
+~~~~~~~~~~~~~
+
+Proxmox Offline Mirror is fully open-source and contributions are welcome! Here
+is the primary communication channel for developers:
+
+:Mailing list for developers: `PVE Development List`_
+
+Bug Tracker
+~~~~~~~~~~~
+
+Proxmox runs a public bug tracker at ``_. If an
+issue appears, file your report there. An issue can be a bug, as well as a
+request for a new feature or enhancement. The bug tracker helps to keep track
+of the issue and will send a notification once it has been solved.
+
+License
+-------
+
+|pom-copyright|
+
+This software is written by Proxmox Server Solutions GmbH
+
+Proxmox Backup Server is free and open source software: you can use it,
+redistribute it, and/or modify it under the terms of the GNU Affero General
+Public License as published by the Free Software Foundation, either version 3
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+``WITHOUT ANY WARRANTY``; without even the implied warranty of
+``MERCHANTABILITY`` or ``FITNESS FOR A PARTICULAR PURPOSE``. See the GNU
+Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see AGPL3_.
\ No newline at end of file
diff --git a/docs/pom-copyright.rst b/docs/pom-copyright.rst
new file mode 100644
index 0000000..86e9434
--- /dev/null
+++ b/docs/pom-copyright.rst
@@ -0,0 +1,18 @@
+Copyright and Disclaimer
+========================
+
+|pom-copyright|
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public
+License along with this program. If not, see
+http://www.gnu.org/licenses/
diff --git a/docs/proxmox-apt-repo/description.rst b/docs/proxmox-apt-repo/description.rst
new file mode 100644
index 0000000..f0c7185
--- /dev/null
+++ b/docs/proxmox-apt-repo/description.rst
@@ -0,0 +1,2 @@
+This tool serves as a helper to streamline usage of a mirrored offline APT
+repository and offline subscription keys.
\ No newline at end of file
diff --git a/docs/proxmox-apt-repo/man1.rst b/docs/proxmox-apt-repo/man1.rst
new file mode 100644
index 0000000..e68a584
--- /dev/null
+++ b/docs/proxmox-apt-repo/man1.rst
@@ -0,0 +1,16 @@
+================
+proxmox-apt-repo
+================
+
+Synopsis
+==========
+
+.. include:: synopsis.rst
+
+Description
+============
+
+.. include:: description.rst
+
+
+.. include:: ../pom-copyright.rst
diff --git a/docs/proxmox-offline-mirror/description.rst b/docs/proxmox-offline-mirror/description.rst
new file mode 100644
index 0000000..69c4b29
--- /dev/null
+++ b/docs/proxmox-offline-mirror/description.rst
@@ -0,0 +1,2 @@
+This tool allows registering and updating offline subscription keys, and
+configuring and managing offline APT repository mirrors and media.
\ No newline at end of file
diff --git a/docs/proxmox-offline-mirror/man1.rst b/docs/proxmox-offline-mirror/man1.rst
new file mode 100644
index 0000000..2127b40
--- /dev/null
+++ b/docs/proxmox-offline-mirror/man1.rst
@@ -0,0 +1,16 @@
+======================
+proxmox-offline-mirror
+======================
+
+Synopsis
+==========
+
+.. include:: synopsis.rst
+
+Description
+============
+
+.. include:: description.rst
+
+
+.. include:: ../pom-copyright.rst
diff --git a/docs/todos.rst b/docs/todos.rst
new file mode 100644
index 0000000..07f44ab
--- /dev/null
+++ b/docs/todos.rst
@@ -0,0 +1,6 @@
+Documentation Todo List
+=======================
+
+This is an auto-generated list of the todo references in the documentation.
+
+.. todolist::
diff --git a/src/bin/docgen.rs b/src/bin/docgen.rs
new file mode 100644
index 0000000..876222d
--- /dev/null
+++ b/src/bin/docgen.rs
@@ -0,0 +1,31 @@
+use anyhow::{bail, Error};
+use proxmox_offline_mirror::config;
+
+use proxmox_section_config::dump_section_config;
+
+fn get_args() -> (String, Vec) {
+ let mut args = std::env::args();
+ let prefix = args.next().unwrap();
+ let prefix = prefix.rsplit('/').next().unwrap().to_string(); // without path
+ let args: Vec = args.collect();
+
+ (prefix, args)
+}
+
+fn main() -> Result<(), Error> {
+ let (_prefix, args) = get_args();
+
+ if args.is_empty() {
+ bail!("missing arguments");
+ }
+
+ for arg in args.iter() {
+ let text = match arg.as_ref() {
+ "mirror.cfg" => dump_section_config(&config::CONFIG),
+ _ => bail!("docgen: got unknown type"),
+ };
+ println!("{}", text);
+ }
+
+ Ok(())
+}
\ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
index 42705a8..44c4ca1 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -176,7 +176,7 @@ impl SubscriptionKey {
}
lazy_static! {
- static ref CONFIG: SectionConfig = init();
+ pub static ref CONFIG: SectionConfig = init();
}
fn init() -> SectionConfig {