├── .coveragerc ├── .dir-locals.el ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab-ci └── commit-rules.yml ├── .gitmodules ├── COPYING ├── HACKING.md ├── Makefile ├── README.md ├── TODO ├── bin ├── gbp-builder-mock └── git-pbuilder ├── debian ├── NEWS ├── bug-presubj ├── changelog ├── clean ├── control ├── copyright ├── gbp.completion ├── gbp.conf ├── git-buildpackage-rpm.install ├── git-buildpackage-rpm.manpages ├── git-buildpackage.bash-completion ├── git-buildpackage.doc-base ├── git-buildpackage.docs ├── git-buildpackage.examples ├── git-buildpackage.install ├── git-buildpackage.links ├── git-buildpackage.manpages ├── not-installed ├── pk4 │ └── gbp ├── rules ├── salsa-ci.yml ├── source │ └── format ├── tests │ ├── control │ └── smoke-rpm └── zsh │ └── _gbp ├── dev_requirements.txt ├── docs ├── Makefile ├── Makefile.lang ├── chapters │ ├── building.xml │ ├── cfgfile.xml │ ├── chapters.ent │ ├── import.xml │ ├── intro.xml │ ├── patches.xml │ ├── releases.xml │ └── special.xml ├── common.ent ├── copyright.xml ├── gbp.css ├── gbp.svg ├── images │ ├── dep-14-branch-examples.svg │ ├── pq-applied.png │ ├── pq-export.png │ ├── pq-rebase.png │ ├── pq-time-machine.png │ └── pq-unapplied.png ├── man.gbp.xml ├── manpages │ ├── gbp-buildpackage-rpm.xml │ ├── gbp-buildpackage.xml │ ├── gbp-clone.xml │ ├── gbp-config.xml │ ├── gbp-create-remote-repo.xml │ ├── gbp-dch.xml │ ├── gbp-export-orig.xml │ ├── gbp-import-dsc.xml │ ├── gbp-import-dscs.xml │ ├── gbp-import-orig.xml │ ├── gbp-import-ref.xml │ ├── gbp-import-srpm.xml │ ├── gbp-pq-rpm.xml │ ├── gbp-pq.xml │ ├── gbp-pristine-tar.xml │ ├── gbp-pull.xml │ ├── gbp-push.xml │ ├── gbp-rpm-ch.xml │ ├── gbp-setup-gitattributes.xml │ ├── gbp-tag.xml │ ├── gbp.conf.xml │ ├── gbp.xml │ ├── man.common-options.ent │ ├── man.conffiles.xml │ ├── man.seealso.xml │ └── manpages.ent ├── manual.xml └── po │ ├── de.po │ ├── gbp.pot │ └── po4a.cfg ├── examples ├── README.source ├── gbp-add-patch ├── gbp-configure-unpatched-source ├── gbp-svn-tag ├── gbp-try-ff ├── gbp-upload ├── jenkins-scratchbuilder ├── wrap_cl.py └── zeitgeist-git.py ├── gbp.conf ├── gbp ├── __init__.py ├── command_wrappers.py ├── config.py ├── dch.py ├── deb │ ├── __init__.py │ ├── changelog.py │ ├── control.py │ ├── dscfile.py │ ├── format.py │ ├── git.py │ ├── policy.py │ ├── pristinetar.py │ ├── rollbackgit.py │ ├── source.py │ ├── upstreamsource.py │ └── uscan.py ├── errors.py ├── format.py ├── git │ ├── __init__.py │ ├── args.py │ ├── commit.py │ ├── errors.py │ ├── fastimport.py │ ├── modifier.py │ ├── repository.py │ └── vfs.py ├── log.py ├── notifications.py ├── patch_series.py ├── paths.py ├── pipes.py ├── pkg │ ├── __init__.py │ ├── archive.py │ ├── compressor.py │ ├── git.py │ ├── pkgpolicy.py │ ├── pristinetar.py │ └── upstreamsource.py ├── rpm │ ├── __init__.py │ ├── changelog.py │ ├── git.py │ ├── lib_rpm.py │ ├── linkedlist.py │ └── policy.py ├── scripts │ ├── __init__.py │ ├── buildpackage.py │ ├── buildpackage_rpm.py │ ├── clone.py │ ├── common │ │ ├── __init__.py │ │ ├── buildpackage.py │ │ ├── hook.py │ │ ├── import_orig.py │ │ ├── pq.py │ │ └── repo_setup.py │ ├── config.py │ ├── create_remote_repo.py │ ├── dch.py │ ├── export_orig.py │ ├── import_dsc.py │ ├── import_dscs.py │ ├── import_orig.py │ ├── import_ref.py │ ├── import_srpm.py │ ├── pq.py │ ├── pq_rpm.py │ ├── pristine_tar.py │ ├── pull.py │ ├── push.py │ ├── rpm_ch.py │ ├── setup_gitattributes.py │ ├── supercommand.py │ └── tag.py ├── tmpfile.py └── tristate.py ├── packaging ├── 0001-Fix-path-to-docbook-dtd-file.patch ├── git-buildpackage.spec └── run-in-container ├── pydoctor.ini ├── pyproject.toml ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── 01_test_help.py ├── 02_test_upstream_source_tar_unpack.py ├── 03_test_dch_guess_version.py ├── 04_test_submodules.py ├── 05_test_detection.py ├── 06_test_upstream_source.py ├── 07_test_fastimport.py ├── 08_test_patch.py ├── 08_test_patch_data ├── 916545.patch ├── base64.patch ├── dep3-iso8859-1.patch ├── dep3-longdesc-bug.patch ├── patch1.diff └── usbip-fix-misuse-of-strncpy.patch ├── 09_test_git_repository.py ├── 10_test_get_upstream_tree.py ├── 11_test_dch_main.py ├── 12_test_deb.py ├── 13_test_gbp_pq.py ├── 14_test_gbp_import_dscs.py ├── 15_test_DebianSource.py ├── 16_test_supercommand.py ├── 17_test_dch_guess_documented_commit.py ├── 18_test_Config.py ├── 19_test_gbp_scripts_config.py ├── 20_test_rpm.py ├── 21_test_command_wrappers.py ├── 22_test_gbp_buildpackage.py ├── 23_test_dch_extract_bts_cmds.py ├── 24_test_gbp_import_orig.py ├── 25_test_broken_gbp_conf.py ├── 26_test_dch_extract_thanks.py ├── 27_test_create_remote_repo.py ├── 28_test_gbp_git_repository_commit_dir.py ├── 29_test_gbp_clone.py ├── 30_test_deb_changelog.py ├── 30_test_rpm_changelog.py ├── 31_test_uscan.py ├── __init__.py ├── component ├── __init__.py ├── deb │ ├── __init__.py │ ├── fixtures.py │ ├── test_buildpackage.py │ ├── test_clone.py │ ├── test_dch.py │ ├── test_export_orig.py │ ├── test_import_dsc.py │ ├── test_import_dscs.py │ ├── test_import_orig.py │ ├── test_import_ref.py │ ├── test_pq.py │ ├── test_pristine_tar.py │ ├── test_pull.py │ ├── test_push.py │ ├── test_setup_gitattributes.py │ └── test_tag.py └── rpm │ ├── __init__.py │ ├── test_buildpackage_rpm.py │ ├── test_import_orig_rpm.py │ ├── test_import_srpm.py │ ├── test_pq_rpm.py │ └── test_rpm_ch.py ├── context.py ├── data ├── brackets-in-subject.patch ├── foo.patch ├── gbp_config.conf ├── gbp_create_remote_repo.conf ├── pristine_tar │ ├── testfile1 │ └── testfile2 ├── rpm │ ├── rpmbuild │ │ ├── SOURCES │ │ │ ├── bar.tar.gz │ │ │ ├── foo.txt │ │ │ ├── gbp-test-1.0.tar.bz2 │ │ │ ├── gbp-test-native-1.0.zip │ │ │ ├── gbp-test2-3.0.tar.gz │ │ │ ├── my.patch │ │ │ ├── my2.patch │ │ │ └── my3.patch │ │ └── SPECS │ │ │ ├── gbp-test-native.spec │ │ │ ├── gbp-test-native2.spec │ │ │ ├── gbp-test.spec │ │ │ └── gbp-test2.spec │ ├── specs │ │ ├── gbp-test-native.spec │ │ ├── gbp-test-native2.spec │ │ ├── gbp-test-quirks.spec │ │ ├── gbp-test-reference.spec │ │ ├── gbp-test-reference2.spec │ │ ├── gbp-test-tags.spec │ │ ├── gbp-test-updates-reference.spec │ │ ├── gbp-test-updates.spec │ │ ├── gbp-test.spec │ │ ├── gbp-test2-reference.spec │ │ ├── gbp-test2-reference2.spec │ │ ├── gbp-test2.spec │ │ └── gbp-test3.spec │ └── srpms │ │ ├── gbp-test-1.0-1.src.rpm │ │ └── gbp-test2-3.0-0.src.rpm └── test1.conf ├── doctests ├── __init__.py ├── test_Changelog.py ├── test_Config.py ├── test_Control.py ├── test_GitModifier.py ├── test_GitRepository.py ├── test_GitVfs.py ├── test_PristineTar.py └── test_create_remote_repo.py ├── test_RollbackDebianGitRepository.py └── testutils ├── __init__.py ├── capture.py ├── data.py ├── debiangittestrepo.py ├── gbplogtester.py └── popen.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | include = gbp/* 3 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ( 2 | (nxml-mode . ( 3 | (indent-tabs-mode . nil) 4 | )) 5 | ) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .coverage 3 | .tox/ 4 | .ropeproject/ 5 | coverage.xml 6 | gbp/version.py 7 | build/ 8 | gbp.egg-info/ 9 | *~ 10 | *.sw? 11 | \#*# 12 | .#* 13 | *.log 14 | *-junit.xml 15 | 16 | docs/*.1 17 | docs/*.5 18 | docs/_gen/ 19 | docs/buildxref/ 20 | docs/manual-html/ 21 | docs/manpage.links 22 | docs/manpage.refs 23 | docs/version.ent 24 | 25 | debian/git-buildpackage*.debhelper* 26 | debian/python-module-stampdir/ 27 | debian/files 28 | debian/git-buildpackage*.substvars 29 | debian/git-buildpackage/ 30 | debian/git-buildpackage-rpm/ 31 | debian/tmp/ 32 | 33 | /venv/ 34 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | include: 3 | - remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/6a40df92957c8ce9ee741aaccc5daaaf70545b1e/templates/ci-fairy.yml' 4 | 5 | default: 6 | # Protect CI infra from rogue jobs 7 | timeout: 15 minutes 8 | # Allow jobs to be caneled on new commits 9 | interruptible: true 10 | # Retry on infra hickups automatically 11 | retry: 12 | max: 1 13 | when: 14 | - 'api_failure' 15 | - 'runner_system_failure' 16 | - 'scheduler_failure' 17 | - 'stuck_or_timeout_failure' 18 | 19 | workflow: 20 | rules: 21 | - if: $CI_PIPELINE_SOURCE == 'merge_request_event' 22 | # Don't trigger a branch pipeline if there is an open MR 23 | - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS 24 | when: never 25 | - if: $CI_COMMIT_TAG 26 | - if: $CI_COMMIT_BRANCH 27 | 28 | variables: 29 | FDO_UPSTREAM_REPO: agx/git-buildpackage 30 | 31 | stages: 32 | - check 33 | - package 34 | 35 | python-lint: 36 | stage: check 37 | image: debian:sid 38 | before_script: 39 | - apt -y update 40 | - apt -y install ruff 41 | script: 42 | # Ruff is fast, run it twice to have junit and stout: 43 | - ruff check --output-format=junit --output-file=ruff-junit.xml . || true 44 | - ruff check . 45 | artifacts: 46 | paths: 47 | - ruff-junit.xml 48 | reports: 49 | junit: ruff-junit.xml 50 | 51 | python-tests: 52 | stage: check 53 | image: debian:sid 54 | variables: 55 | PYTEST_ARGS: --junit-xml=pytest-junit.xml --cov --cov-report term --cov-report xml:coverage.xml 56 | before_script: 57 | # Some tests need sources configured for e.g. "apt showsrc" 58 | - echo "deb-src http://deb.debian.org/debian/ sid main" > /etc/apt/sources.list.d/sid-src.list 59 | - apt -y update 60 | - apt -y install curl python3-requests flake8 61 | - apt -y build-dep . 62 | script: 63 | - git submodule update --init -- tests/component/deb/data/ 64 | - python3 setup.py build 65 | - make syntax-check 66 | - GBP_NETWORK_TESTS=1 make test 67 | coverage: '/TOTAL.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' 68 | artifacts: 69 | paths: 70 | - pytest-junit.xml 71 | reports: 72 | junit: pytest-junit.xml 73 | coverage_report: 74 | coverage_format: cobertura 75 | path: coverage.xml 76 | 77 | python-typecheck: 78 | stage: check 79 | image: debian:sid 80 | variables: 81 | MYPY_ARGS: --junit-xml=mypy-junit.xml 82 | before_script: 83 | - apt -y update 84 | - apt -y build-dep . 85 | - apt -y install mypy 86 | script: 87 | - python3 setup.py build 88 | - make type-check 89 | artifacts: 90 | paths: 91 | - mypy-junit.xml 92 | reports: 93 | junit: mypy-junit.xml 94 | 95 | shellcheck: 96 | stage: check 97 | image: debian:sid 98 | before_script: 99 | - apt -y update 100 | - apt -y install shellcheck bash zsh make 101 | script: 102 | - make shell-check 103 | 104 | codespell: 105 | stage: check 106 | image: debian:sid 107 | before_script: 108 | - apt -y update 109 | - apt -y install codespell 110 | script: 111 | - codespell docs/ 112 | 113 | # Sanity checks of MR settings and commit logs 114 | sanity: 115 | extends: 116 | - .fdo.ci-fairy 117 | stage: check 118 | variables: 119 | GIT_DEPTH: "100" 120 | needs: [] 121 | script: | 122 | ci-fairy check-commits --signed-off-by --junit-xml=commit-message-junit-report.xml 123 | artifacts: 124 | reports: 125 | junit: commit-message-junit-report.xml 126 | rules: 127 | - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME' 128 | 129 | salsaci: 130 | stage: package 131 | trigger: 132 | include: debian/salsa-ci.yml 133 | strategy: depend 134 | -------------------------------------------------------------------------------- /.gitlab-ci/commit-rules.yml: -------------------------------------------------------------------------------- 1 | patterns: 2 | deny: 3 | - regex: '^$CI_MERGE_REQUEST_PROJECT_URL/(-/)?merge_requests/$CI_MERGE_REQUEST_IID$' 4 | message: Commit message must not contain a link to its own merge request 5 | - regex: '^[^:]+: [a-z]' 6 | message: "Commit description in commit message subject should be properly Capitalized. E.g. 'monitor: Avoid crash on unplug'" 7 | where: subject 8 | - regex: '^\S*\.(c|h|py|ui):' 9 | message: Commit message subject prefix should not include .c, .h etc. 10 | where: subject 11 | - regex: '([^.]\.|[:,;])\s*$' 12 | message: Commit message subject should not end with punctuation 13 | where: subject 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests/component/deb/data"] 2 | path = tests/component/deb/data 3 | url = https://git.sigxcpu.org/cgit/gbp/deb-testdata 4 | [submodule "tests/component/rpm/data"] 5 | path = tests/component/rpm/data 6 | url = https://git.sigxcpu.org/cgit/gbp/rpm-testdata 7 | 8 | -------------------------------------------------------------------------------- /HACKING.md: -------------------------------------------------------------------------------- 1 | Running the Tests 2 | ----------------- 3 | 4 | The tests are run via 5 | 6 | ```sh 7 | make 8 | ``` 9 | 10 | To also run the component tests, you need to initialize the git submodules once 11 | via: 12 | 13 | ```sh 14 | git submodule update --init --recursive 15 | ``` 16 | 17 | This will fetch the necessary binary data for the DEB and RPM component tests, 18 | and the tests are from now on included within each regular test run. 19 | 20 | Some tests reach out to the network. To run these in addition to all 21 | other tests use: 22 | 23 | ```sh 24 | make all+net 25 | ``` 26 | 27 | You can run the tests in a `debian:sid` docker container by using 28 | 29 | ```sh 30 | packaging/run-in-container 31 | ``` 32 | 33 | The python tests use `pytest` so you can use all it's options. To run a 34 | single test e.g. 35 | 36 | ```sh 37 | pytest tests/component/deb/test_push.py::TestPush::test_push_failure 38 | ``` 39 | 40 | If you want to keep any temporary repos around for inspection use 41 | `GBP_TESTS_NOCLEAN`: 42 | 43 | ```sh 44 | GBP_TESTS_NOCLEAN=1 pytest tests/component/deb/test_push.py::TestPush::test_push_failure 45 | ``` 46 | 47 | Building the API Docs 48 | --------------------- 49 | 50 | You can build the API docs using 51 | 52 | ```sh 53 | make apidocs 54 | ``` 55 | 56 | Contributing Patches 57 | -------------------- 58 | 59 | Make sure the tests pass before sending in patch. You can either send 60 | it to the mailing list, add it to a bug report against 61 | git-buildpackage on or 62 | open a merge request at 63 | 64 | 65 | Please add a `Signed-off-by:` to commit messages to indicate that you agree to 66 | the [Developer's Certificate of Origin][]. 67 | 68 | If you fix a regression or add a new feature please make sure this is covered 69 | by either a unittest (`tests/*.py`) or a component test that exercises one of the 70 | scripts (`tests/component/{deb,rpm}/*.py`). 71 | 72 | Layout 73 | ------ 74 | 75 | gbp/scripts/*.py - the actual gbp commands (buildpackage, dch, …) 76 | gbp/scripts/common/ - code shared between Debian and RPM commands 77 | gbp/deb/ - Debian package handling (control, dsc, …) 78 | gbp/rpm/ - RPM package handling (spec files, …) 79 | gbp/git/ - Git repository interaction 80 | tests/*.py - unit tests 81 | tests/doctests - doctests that also serve as examples 82 | tests/component/ - component tests that invoke actual commands 83 | 84 | Interfaces 85 | ---------- 86 | 87 | A gbp command in `gbp/scripts/.py` must provide these interfaces: 88 | 89 | When one invokes `gbp ` `gbp/scripts/.py` is imported by 90 | 91 | gbp/scripts/supercommand.py 92 | 93 | which then invokes it's *main* function with all given command line arguments. 94 | It is expected to return with the exit status that should be passed back to the 95 | shell. 96 | 97 | When one invokes `gbp config ` `gbp/scripts/.py` is imported by 98 | 99 | gbp/scripts/config.py 100 | 101 | which then invokes it's *build_parser* function with the command name as argument. 102 | It is expected to return a `GbpConfigParser` with all config files parsed. 103 | 104 | [Developer's Certificate of Origin]: https://developercertificate.org/ 105 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PYTHON=python3 2 | PY_EXAMPLES=$(shell grep -l /usr/bin/python examples/*) 3 | FLAKE_OPTS=$(shell test -w /dev/shm || echo '-j1') 4 | TEST_LOCALE?=C.UTF-8 5 | 6 | SH_SCRIPTS = \ 7 | packaging/run-in-container \ 8 | $(NULL) 9 | 10 | all: syntax-check test 11 | 12 | all+net: 13 | GBP_NETWORK_TESTS=1 $(MAKE) all 14 | 15 | test: 16 | export HOME=/nonexisting; \ 17 | export GIT_AUTHOR_NAME="Gbp Tests"; \ 18 | export GIT_AUTHOR_EMAIL=tests@example.com; \ 19 | export GIT_COMMITTER_NAME=$$GIT_AUTHOR_NAME; \ 20 | export GIT_COMMITTER_EMAIL=$$GIT_AUTHOR_EMAIL; \ 21 | export DEBEMAIL=$$GIT_AUTHOR_EMAIL; \ 22 | PYTHONPATH=. \ 23 | LC_ALL=$(TEST_LOCALE) \ 24 | $(PYTHON) -m pytest $(PYTEST_ARGS) 25 | 26 | syntax-check: 27 | flake8 $(FLAKE_OPTS) 28 | flake8 $(FLAKE_OPTS) $(PY_EXAMPLES) 29 | 30 | type-check: 31 | mypy $(MYPY_ARGS) gbp 32 | 33 | shell-check: 34 | @echo "# Validating zsh completion" 35 | zsh debian/zsh/_gbp 36 | @echo "# Validating bash completion" 37 | shellcheck --shell=bash debian/git-buildpackage.bash-completion 38 | shellcheck $(SH_SCRIPTS) 39 | 40 | docs: 41 | $(MAKE) -C docs 42 | $(MAKE) apidocs 43 | 44 | apidocs: 45 | mkdir -p build 46 | 47 | venv: venv/stamp 48 | venv/stamp: 49 | $(PYTHON) -m venv venv 50 | . venv/bin/activate && pip install -r dev_requirements.txt 51 | touch '$@' 52 | 53 | .PHONY: docs venv 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Git-buildpackage 2 | ================ 3 | 4 | Tools to ease the development of Debian and (partially) RPM packages in git 5 | repositories. For documentation see the manual online at: 6 | 7 | 8 | 9 | On Debian systems, the documentation can be found in 10 | /usr/share/doc/git-buildpackage/manual-html. 11 | 12 | The API documentation of the gbp module can be found at: 13 | 14 | 15 | 16 | The mailing list is at: 17 | 18 | * 19 | * git-buildpackage at lists.sigxcpu.org 20 | 21 | See the [HACKING](./HACKING.md) document for details on contributing 22 | to gbp development. The package is also available on Pypi at 23 | . 24 | 25 | ![gbp logo](docs/gbp.svg) 26 | 27 | [![Build Status](https://travis-ci.org/agx/git-buildpackage.svg?branch=master)](https://travis-ci.org/agx/git-buildpackage) 28 | [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1311/badge)](https://bestpractices.coreinfrastructure.org/projects/1311) 29 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | See https://honk.sigxcpu.org/piki/projects/git-buildpackage/ 2 | -------------------------------------------------------------------------------- /bin/gbp-builder-mock: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Helper to invoke mock from 'gbp buildpackage-rpm' 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | # 19 | # Copyright (C) 2015 Tzafrir Cohen 20 | # (C) 2015 Guido Gunther 21 | 22 | set -e 23 | 24 | # There must be a saner way to do that or a reason why this is not required 25 | fix_arch() { 26 | GBP_BUILDER_MOCK_ARCH=${GBP_BUILDER_MOCK_ARCH:-`uname -m`} 27 | case "$ARCH" in 28 | amd64) ARCH='x86_64';; 29 | esac 30 | } 31 | 32 | 33 | usage() { 34 | EXIT=${1:-1} 35 | echo >&2 "$0: Must be run via 'gbp buildpackage-rpm', see manpage for details" 36 | exit $EXIT 37 | } 38 | 39 | while [ $# != 0 ]; do 40 | case "$1" in 41 | --help|-h|-\?) usage 0;; 42 | *.spec) SPEC="$1";; 43 | esac 44 | shift 45 | done 46 | 47 | # Make sure we have the necessary tools. 48 | if [ ! -x /usr/bin/mock ]; then 49 | echo "mock not found; you need to install the mock package" >&2 50 | exit 1 51 | fi 52 | 53 | gbp_builder_mock() { 54 | if [ -z "$GBP_BUILDER_MOCK_DIST" ]; then 55 | usage 56 | fi 57 | local root=${GBP_BUILDER_MOCK_ROOT:-${GBP_BUILDER_MOCK_DIST}-${GBP_BUILDER_MOCK_ARCH}} 58 | if [ ! -d "$GBP_BUILDER_MOCK_EXPORT_DIR" ]; then 59 | echo >&2 "$0: Missing output directory (GBP_BUILDER_MOCK_EXPORT_DIR). Aborting." 60 | usage 61 | fi 62 | if [ -z "$SPEC" ]; then 63 | echo >&2 "$0: No specfile given." 64 | exit 1 65 | fi 66 | export_dir="$PWD" 67 | spec="$export_dir/SPECS/$SPEC" 68 | sources="$export_dir/SOURCES" 69 | srpms="$export_dir/SRPMS" 70 | pat="${GBP_BUILDER_MOCK_RESULTS_PAT-results/{{dist\}\}/{{target_arch\}\}/}" 71 | local resultdir="$export_dir/$pat" 72 | local mock="mock -r $root --sources=$sources ${GBP_BUILDER_MOCK_OPTIONS}" 73 | 74 | $mock --resultdir=$srpms --spec=$spec --buildsrpm 75 | # Assuming that nothing was built in this directory since the previous command: 76 | local srpm=`ls -t $PWD/SRPMS/*.src.rpm 2>/dev/null| head -n1` 77 | if [ -z $srpm ]; then 78 | echo >&2 "$0: failed to create srpm" 79 | exit 1 80 | fi 81 | $mock --no-cleanup-after --resultdir $resultdir --rebuild "$srpm" 82 | } 83 | 84 | 85 | fix_arch 86 | gbp_builder_mock 87 | -------------------------------------------------------------------------------- /debian/bug-presubj: -------------------------------------------------------------------------------- 1 | When reporting issues regarding git-buildpackage please run the failing command 2 | with --git-verbose (gbp buildpackage) or --verbose (all other commands) and 3 | provide the full output. 4 | -------------------------------------------------------------------------------- /debian/clean: -------------------------------------------------------------------------------- 1 | build/ 2 | gbp.egg-info/ 3 | gbp/version.py 4 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: git-buildpackage 2 | Section: vcs 3 | Priority: optional 4 | Maintainer: Guido Günther 5 | Build-Depends: 6 | bash-completion (>= 1:2.1-4.2~), 7 | debhelper-compat (= 13), 8 | dh-python, 9 | dh-sequence-bash-completion, 10 | dh-sequence-python3, 11 | docbook2x, 12 | gtk-doc-tools, 13 | libdistro-info-perl, 14 | perl, 15 | pydoctor, 16 | python3, 17 | python3-setuptools, 18 | xsltproc, 19 | # For the testsuite 20 | bzip2 , 21 | cpio , 22 | devscripts (>= 2.17.7~) , 23 | git (>= 1:2.40.1) , 24 | pristine-tar (>= 1.14) , 25 | python3-dateutil , 26 | python3-pytest , 27 | python3-pytest-cov , 28 | python3-rpm , 29 | python3-yaml , 30 | rpm (>= 4.16.1) , 31 | unzip , 32 | zipmerge , 33 | Standards-Version: 4.6.1 34 | Vcs-Git: https://salsa.debian.org/agx/git-buildpackage.git 35 | Vcs-Browser: https://salsa.debian.org/agx/git-buildpackage/ 36 | Homepage: https://honk.sigxcpu.org/piki/projects/git-buildpackage/ 37 | Rules-Requires-Root: no 38 | X-Python3-Version: >= 3.12 39 | 40 | Package: git-buildpackage 41 | Architecture: all 42 | Depends: ${python3:Depends}, 43 | ${shlibs:Depends}, 44 | ${misc:Depends}, 45 | devscripts (>= 2.25.2~), 46 | git (>= 1:2.40.1-1), 47 | man-db, 48 | python3-dateutil, 49 | python3-yaml, 50 | sensible-utils, 51 | Recommends: pristine-tar (>= 1.41), 52 | cowbuilder | pbuilder | sbuild, 53 | python3-requests 54 | Breaks: dgit (<< 9.16~) 55 | Suggests: python3-notify2, unzip, sudo 56 | Description: Suite to help with Debian packages in Git repositories 57 | This package contains the following tools: 58 | * gbp buildpackage: build a package out of a Git repository, check for local 59 | modifications and tag appropriately 60 | * gbp import-orig: import a new upstream version into the Git repository 61 | * gbp export-orig: export an upstream tarball from the Git repository 62 | * gbp import-{dsc,dscs}: import existing Debian source packages into a Git 63 | repository 64 | * gbp dch: generate Debian changelog entries from Git commit messages 65 | * gbp {pull,clone}: clone and pull from remote repos 66 | * gbp pq: manage debian/patches easily 67 | * gbp create-remote-repo: create remote repositories 68 | * gbp push: push content to remote repositories 69 | * gbp tag: tag a Debian package in Git 70 | * gbp pristine-tar: create pristine-tar commits 71 | * gbp setup-gitattributes: set up Git attributes to disable transformations 72 | 73 | Package: git-buildpackage-rpm 74 | Architecture: all 75 | Depends: ${python3:Depends}, 76 | ${misc:Depends}, 77 | cpio, 78 | git-buildpackage (= ${binary:Version}), 79 | python3-rpm (>= 4.16.1), 80 | rpm (>= 4.16.1), 81 | Recommends: pristine-tar (>= 0.5) 82 | Suggests: python3-notify2, unzip, zipmerge, mock 83 | Description: Suite to help with RPM packages in Git repositories 84 | This package contains the following tools: 85 | * gbp buildpackage-rpm: build a package out of a Git repository, check for 86 | local modifications and tag appropriately 87 | * gbp import-srpm: import existing RPM source packages into a Git 88 | repository 89 | * gbp pq-rpm: manage patches easily 90 | . 91 | These tools are currently in an experimental state. Branch names and 92 | repository layouts might change without lots of prior warning. 93 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | 3 | Files: * 4 | Copyright: 5 | 2006-2022 Guido Günther 6 | License: GPL-2 7 | You are free to distribute this software under the terms of the GNU General 8 | Public License Version 2. The full text of this license can be found in the 9 | file /usr/share/common-licenses/GPL-2 10 | 11 | Files: bin/git-pbuilder 12 | Copyright: 13 | 2014-2016 Russ Allbery 14 | 2008-2013 The Board of Trustees of the Leland Stanford Junior University 15 | License: expat-variant 16 | Permission to use, copy, modify, and distribute this software and its 17 | documentation for any purpose and without fee is hereby granted, provided 18 | that the above copyright notice appear in all copies and that both that 19 | copyright notice and this permission notice appear in supporting 20 | documentation, and that the name of Stanford University not be used in 21 | advertising or publicity pertaining to distribution of the software without 22 | specific, written prior permission. Stanford University makes no 23 | representations about the suitability of this software for any purpose. It 24 | is provided "as is" without express or implied warranty. 25 | -------------------------------------------------------------------------------- /debian/gbp.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | debian-branch = master 3 | 4 | [dch] 5 | id-length = 7 6 | postedit = sed -i s"!^Version:.*!Version: $GBP_DEBIAN_VERSION!" packaging/git-buildpackage.spec 7 | -------------------------------------------------------------------------------- /debian/git-buildpackage-rpm.install: -------------------------------------------------------------------------------- 1 | usr/bin/gbp-builder-mock /usr/share/git-buildpackage/ 2 | usr/lib/python3.*/dist-packages/gbp/rpm usr/lib/python3/dist-packages/gbp/ 3 | usr/lib/python3.*//dist-packages/gbp/scripts/import_srpm.py usr/lib/python3/dist-packages/gbp/scripts/ 4 | usr/lib/python3.*/dist-packages/gbp/scripts/pq_rpm.py usr/lib/python3/dist-packages/gbp/scripts/ 5 | usr/lib/python3.*/dist-packages/gbp/scripts/buildpackage_rpm.py usr/lib/python3/dist-packages/gbp/scripts/ 6 | usr/lib/python3.*/dist-packages/gbp/scripts/rpm_ch.py usr/lib/python3/dist-packages/gbp/scripts/ 7 | -------------------------------------------------------------------------------- /debian/git-buildpackage-rpm.manpages: -------------------------------------------------------------------------------- 1 | docs/gbp-import-srpm.1 2 | docs/gbp-pq-rpm.1 3 | docs/gbp-buildpackage-rpm.1 4 | docs/gbp-rpm-ch.1 5 | -------------------------------------------------------------------------------- /debian/git-buildpackage.bash-completion: -------------------------------------------------------------------------------- 1 | debian/gbp.completion gbp 2 | -------------------------------------------------------------------------------- /debian/git-buildpackage.doc-base: -------------------------------------------------------------------------------- 1 | Document: git-buildpackage 2 | Title: Git-Buildpackage Manual 3 | Author: Guido Günther 4 | Abstract: git-buildpackage is a suite to help with Debian packages in Git 5 | repositories. This manual describes the utilities in this package, their 6 | configuration and possible workflows. 7 | Section: Programming 8 | 9 | Format: HTML 10 | Index: /usr/share/doc/git-buildpackage/manual-html/index.html 11 | Files: /usr/share/doc/git-buildpackage/manual-html/*.html 12 | -------------------------------------------------------------------------------- /debian/git-buildpackage.docs: -------------------------------------------------------------------------------- 1 | README.md 2 | docs/manual-html/ 3 | -------------------------------------------------------------------------------- /debian/git-buildpackage.examples: -------------------------------------------------------------------------------- 1 | examples/* 2 | -------------------------------------------------------------------------------- /debian/git-buildpackage.install: -------------------------------------------------------------------------------- 1 | debian/zsh/_gbp usr/share/zsh/vendor-completions 2 | debian/pk4/gbp usr/share/pk4/hooks-available/unpack 3 | usr/bin/gbp 4 | usr/bin/git-pbuilder 5 | usr/lib/python3.*/dist-packages/gbp-* usr/lib/python3/dist-packages/ 6 | usr/lib/python3.*/dist-packages/gbp/command_wrappers.py usr/lib/python3/dist-packages/gbp/ 7 | usr/lib/python3.*/dist-packages/gbp/config.py usr/lib/python3/dist-packages/gbp/ 8 | usr/lib/python3.*/dist-packages/gbp/dch.py usr/lib/python3/dist-packages/gbp/ 9 | usr/lib/python3.*/dist-packages/gbp/deb/ usr/lib/python3/dist-packages/gbp/ 10 | usr/lib/python3.*/dist-packages/gbp/errors.py usr/lib/python3/dist-packages/gbp/ 11 | usr/lib/python3.*/dist-packages/gbp/format.py usr/lib/python3/dist-packages/gbp/ 12 | usr/lib/python3.*/dist-packages/gbp/git/ usr/lib/python3/dist-packages/gbp/ 13 | usr/lib/python3.*/dist-packages/gbp/__init__.py usr/lib/python3/dist-packages/gbp/ 14 | usr/lib/python3.*/dist-packages/gbp/log.py usr/lib/python3/dist-packages/gbp/ 15 | usr/lib/python3.*/dist-packages/gbp/notifications.py usr/lib/python3/dist-packages/gbp/ 16 | usr/lib/python3.*/dist-packages/gbp/paths.py usr/lib/python3/dist-packages/gbp/ 17 | usr/lib/python3.*/dist-packages/gbp/patch_series.py usr/lib/python3/dist-packages/gbp/ 18 | usr/lib/python3.*/dist-packages/gbp/pipes.py usr/lib/python3/dist-packages/gbp/ 19 | usr/lib/python3.*/dist-packages/gbp/pkg/ usr/lib/python3/dist-packages/gbp/ 20 | usr/lib/python3.*/dist-packages/gbp/scripts/buildpackage.py usr/lib/python3/dist-packages/gbp/scripts/ 21 | usr/lib/python3.*/dist-packages/gbp/scripts/clone.py usr/lib/python3/dist-packages/gbp/scripts/ 22 | usr/lib/python3.*/dist-packages/gbp/scripts/common/ usr/lib/python3/dist-packages/gbp/scripts/ 23 | usr/lib/python3.*/dist-packages/gbp/scripts/config.py usr/lib/python3/dist-packages/gbp/scripts/ 24 | usr/lib/python3.*/dist-packages/gbp/scripts/create_remote_repo.py usr/lib/python3/dist-packages/gbp/scripts/ 25 | usr/lib/python3.*/dist-packages/gbp/scripts/dch.py usr/lib/python3/dist-packages/gbp/scripts/ 26 | usr/lib/python3.*/dist-packages/gbp/scripts/import_dsc.py usr/lib/python3/dist-packages/gbp/scripts/ 27 | usr/lib/python3.*/dist-packages/gbp/scripts/import_dscs.py usr/lib/python3/dist-packages/gbp/scripts/ 28 | usr/lib/python3.*/dist-packages/gbp/scripts/import_orig.py usr/lib/python3/dist-packages/gbp/scripts/ 29 | usr/lib/python3.*/dist-packages/gbp/scripts/import_ref.py usr/lib/python3/dist-packages/gbp/scripts/ 30 | usr/lib/python3.*/dist-packages/gbp/scripts/export_orig.py usr/lib/python3/dist-packages/gbp/scripts/ 31 | usr/lib/python3.*/dist-packages/gbp/scripts/__init__.py usr/lib/python3/dist-packages/gbp/scripts/ 32 | usr/lib/python3.*/dist-packages/gbp/scripts/pq.py usr/lib/python3/dist-packages/gbp/scripts/ 33 | usr/lib/python3.*/dist-packages/gbp/scripts/pristine_tar.py usr/lib/python3/dist-packages/gbp/scripts/ 34 | usr/lib/python3.*/dist-packages/gbp/scripts/pull.py usr/lib/python3/dist-packages/gbp/scripts/ 35 | usr/lib/python3.*/dist-packages/gbp/scripts/push.py usr/lib/python3/dist-packages/gbp/scripts/ 36 | usr/lib/python3.*/dist-packages/gbp/scripts/setup_gitattributes.py usr/lib/python3/dist-packages/gbp/scripts/ 37 | usr/lib/python3.*/dist-packages/gbp/scripts/supercommand.py usr/lib/python3/dist-packages/gbp/scripts/ 38 | usr/lib/python3.*/dist-packages/gbp/scripts/tag.py usr/lib/python3/dist-packages/gbp/scripts/ 39 | usr/lib/python3.*/dist-packages/gbp/tmpfile.py usr/lib/python3/dist-packages/gbp/ 40 | usr/lib/python3.*/dist-packages/gbp/tristate.py usr/lib/python3/dist-packages/gbp/ 41 | usr/lib/python3.*/dist-packages/gbp/version.py usr/lib/python3/dist-packages/gbp/ 42 | usr/share/git_buildpackage/gbp.conf etc/git-buildpackage/ 43 | -------------------------------------------------------------------------------- /debian/git-buildpackage.links: -------------------------------------------------------------------------------- 1 | /usr/share/man/man1/gbp.1.gz /usr/share/man/man1/git-buildpackage.1.gz 2 | /usr/lib/python3/dist-packages/gbp/scripts/supercommand.py /usr/bin/gbp 3 | -------------------------------------------------------------------------------- /debian/git-buildpackage.manpages: -------------------------------------------------------------------------------- 1 | docs/gbp.1 2 | docs/gbp-buildpackage.1 3 | docs/gbp-clone.1 4 | docs/gbp.conf.5 5 | docs/gbp-config.1 6 | docs/gbp-create-remote-repo.1 7 | docs/gbp-dch.1 8 | docs/gbp-export-orig.1 9 | docs/gbp-import-dsc.1 10 | docs/gbp-import-dscs.1 11 | docs/gbp-import-orig.1 12 | docs/gbp-import-ref.1 13 | docs/gbp-pq.1 14 | docs/gbp-pristine-tar.1 15 | docs/gbp-pull.1 16 | docs/gbp-push.1 17 | docs/gbp-setup-gitattributes.1 18 | docs/gbp-tag.1 19 | docs/git-pbuilder.1 20 | -------------------------------------------------------------------------------- /debian/not-installed: -------------------------------------------------------------------------------- 1 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/deb/__pycache__ 2 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/git/__pycache__ 3 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/pkg/__pycache__ 4 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/__pycache__ 5 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/rpm/__pycache__ 6 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/scripts/common/__pycache__ 7 | debian/tmp/usr/lib/python3.*/dist-packages/gbp/scripts/__pycache__ 8 | 9 | -------------------------------------------------------------------------------- /debian/pk4/gbp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | gbp import-dsc --debian-branch=pk4 --upstream-branch=upstream "$1" "$2" 5 | # Add local gbp.conf to override any branch settings in 'debian/gbp.conf' 6 | # (since this checkout wasn't created by "gbp clone"). We want to be sure the 7 | # branches exist so we can build the package right away. 8 | cat < "$2"/.git/gbp.conf 9 | [DEFAULT] 10 | upstream-branch = upstream 11 | debian-branch = pk4 12 | EOF 13 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ --buildsystem=pybuild 5 | 6 | override_dh_auto_test: 7 | ifeq ($(filter nocheck,$(DEB_BUILD_OPTIONS)),) 8 | make test 9 | endif 10 | 11 | execute_after_dh_auto_build: 12 | make docs 13 | 14 | execute_after_dh_fixperms: 15 | chmod a+x debian/git-buildpackage/usr/lib/python3/dist-packages/gbp/scripts/supercommand.py 16 | 17 | execute_after_dh_auto_clean: 18 | make -C docs/ clean 19 | find gbp -name __init__.py -printf '%h/__pycache__/\n' | xargs rm -fr 20 | -------------------------------------------------------------------------------- /debian/salsa-ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | include: 3 | - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml 4 | - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml 5 | 6 | # Reprotest triggers a test failure not related to reproducibility 7 | variables: 8 | SALSA_CI_DISABLE_REPROTEST: 1 9 | SALSA_CI_DISABLE_VERSION_BUMP: 1 10 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /debian/tests/control: -------------------------------------------------------------------------------- 1 | Tests: smoke-rpm 2 | Depends: @, @builddeps@ 3 | Restrictions: allow-stderr 4 | -------------------------------------------------------------------------------- /debian/tests/smoke-rpm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | cleanup() 7 | { 8 | [ -z "${GBP_TEMPDIR}" ] || rm -rf "${GBP_TEMPDIR}" 9 | } 10 | 11 | trap cleanup EXIT 12 | 13 | git init . 14 | git config user.email "you@example.com" 15 | git config user.name "Doesnot Matter" 16 | git add . 17 | git commit -m"Smoketest" -a 18 | 19 | gbp buildpackage-rpm --help 20 | 21 | # Build an RPM of ourselves if build-deps are available 22 | if python3 -c "import setuptools"; then 23 | GBP_TEMPDIR=$(mktemp -d) 24 | gbp buildpackage-rpm --git-packaging-dir=packaging/ \ 25 | --git-export-dir="$GBP_TEMPDIR" \ 26 | -D'%__python3 /usr/bin/python3' \ 27 | -D'%__python /usr/bin/python3' \ 28 | -D'%python_sitelib %(%{__python3} -Ic "from sysconfig import get_path; print(get_path('"'platlib'"', '"'posix_prefix'"'))")' \ 29 | -D'%_arch noarch' \ 30 | -bb --nodeps 31 | fi 32 | -------------------------------------------------------------------------------- /dev_requirements.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | 3 | flake8 4 | pytest 5 | pytest-cov 6 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make 2 | 3 | MAN1S = \ 4 | gbp \ 5 | gbp-buildpackage \ 6 | gbp-clone \ 7 | gbp-config \ 8 | gbp-create-remote-repo \ 9 | gbp-dch \ 10 | gbp-export-orig \ 11 | gbp-import-dsc \ 12 | gbp-import-dscs \ 13 | gbp-import-orig \ 14 | gbp-import-ref \ 15 | gbp-pq \ 16 | gbp-pristine-tar \ 17 | gbp-pull \ 18 | gbp-push \ 19 | gbp-setup-gitattributes \ 20 | gbp-tag \ 21 | gbp-buildpackage-rpm \ 22 | gbp-import-srpm \ 23 | gbp-pq-rpm \ 24 | gbp-rpm-ch \ 25 | $(NULL) 26 | 27 | MAN5S = \ 28 | gbp.conf \ 29 | $(NULL) 30 | 31 | MANUAL=manual-html 32 | XML_MANPAGES=$(patsubst %,%.1,$(MAN1S)) $(patsubst %,%.5,$(MAN5S)) 33 | POD_MANPAGES=git-pbuilder.1 34 | MANPAGES=$(XML_MANPAGES) $(POD_MANPAGES) 35 | VERSION_ENT=version.ent 36 | GBP_VERSION=../gbp/version.py 37 | DEB_VERSION=$(shell sed -ne 's/^gbp_version\s\+=\s\+"\([.a-z0-9~-]\+\)"/\1/p' $(GBP_VERSION)) 38 | CHANGELOG=../debian/changelog 39 | MAN_DATE=$(shell dpkg-parsechangelog -l ../debian/changelog -SDate | TZ=UTC LC_ALL=C date -f- +'%d %B %Y') 40 | IMAGES=$(wildcard images/*) 41 | DEST_IMAGES=$(subst images/,$(MANUAL)/images/,$(IMAGES)) 42 | 43 | # Select python 44 | ifneq ($(strip $(shell which python3)),) 45 | PYTHON=python3 46 | else 47 | PYTHON=python 48 | endif 49 | 50 | # Select docbook-to-man tool 51 | ifneq ($(strip $(shell which docbook2x-man)),) 52 | DOCBOOK_TO_MAN=docbook2x-man 53 | else ifneq ($(strip $(shell which docbook-to-man)),) 54 | DOCBOOK_TO_MAN=docbook-to-man 55 | else ifneq ($(strip $(shell which docbook2man)),) 56 | DOCBOOK_TO_MAN=docbook2man 57 | else 58 | $(error Unable to find usable docbook to man conversion tool) 59 | endif 60 | 61 | all: manual $(MANPAGES) 62 | 63 | manual: $(MANUAL)/index.html $(DEST_IMAGES) css 64 | 65 | $(MANUAL)/index.html: manual.xml chapters/*.xml manpages/*.xml common.ent $(VERSION_ENT) 66 | mkdir -p $(MANUAL) 67 | xsltproc -o $(MANUAL)/ /usr/share/gtk-doc/data/gtk-doc.xsl $< 68 | cp /usr/share/gtk-doc/data/*.png \ 69 | /usr/share/gtk-doc/data/*.css \ 70 | $(MANUAL) 71 | 72 | $(MANUAL)/gbp.pdf: manual.xml chapters/*.xml manpages/*.xml common.ent $(VERSION_ENT) 73 | xsltproc -o $(MANUAL)/ /usr/share/gtk-doc/data/gtk-doc.xsl $< 74 | 75 | css: $(MANUAL)/gbp.css $(MANUAL)/gbp.svg 76 | $(MANUAL)/gbp.css $(MANUAL)/gbp.svg: gbp.css gbp.svg 77 | cp gbp.css gbp.svg $(MANUAL)/ 78 | 79 | html_images: $(DEST_IMAGES) 80 | $(MANUAL)/images/%: images/% 81 | mkdir -p $(basename $@) 82 | install $< $@ 83 | 84 | %.1 %.5: man.gbp.xml manpages/%.xml 85 | $(DOCBOOK_TO_MAN) -o . $< 86 | 87 | git-pbuilder.1: ../bin/git-pbuilder 88 | pod2man $< $@ 89 | 90 | manual.xml: $(VERSION_ENT) 91 | 92 | $(GBP_VERSION): ../debian/changelog 93 | cd .. && $(PYTHON) setup.py build --help >/dev/null 94 | 95 | $(VERSION_ENT): $(GBP_VERSION) 96 | echo '' > $(VERSION_ENT) 97 | 98 | clean: 99 | -rm -r $(MANUAL) 100 | -rm *.1 *.5 $(VERSION_ENT) 101 | 102 | po4a: 103 | po4a -v -f po/po4a.cfg 104 | 105 | langs: po4a 106 | $(MAKE) -C _gen/de -f ../../Makefile.lang 107 | -------------------------------------------------------------------------------- /docs/Makefile.lang: -------------------------------------------------------------------------------- 1 | MANUAL = manual-html 2 | 3 | ENTS = \ 4 | manpages/manpages.ent \ 5 | manpages/man.common-options.ent \ 6 | chapters/chapters.ent \ 7 | version.ent \ 8 | common.ent \ 9 | $(NULL) 10 | 11 | all: $(MANUAL)/index.html 12 | 13 | manpages/manpages.ent: ../../manpages/manpages.ent 14 | cp -f $< $@ 15 | 16 | manpages/man.common-options.ent: ../../manpages/man.common-options.ent 17 | cp -f $< $@ 18 | 19 | chapters/chapters.ent: ../../chapters/chapters.ent 20 | cp -f $< $@ 21 | 22 | version.ent: ../../version.ent 23 | cp -f $< $@ 24 | 25 | common.ent: ../../common.ent 26 | cp -f $< $@ 27 | 28 | $(MANUAL)/index.html: manual.xml chapters/*.xml manpages/*.xml $(ENTS) 29 | mkdir -p $(MANUAL) 30 | xsltproc -o $(MANUAL)/ /usr/share/gtk-doc/data/gtk-doc.xsl $< 31 | cp /usr/share/gtk-doc/data/*.png \ 32 | /usr/share/gtk-doc/data/*.css \ 33 | $(MANUAL) 34 | -------------------------------------------------------------------------------- /docs/chapters/chapters.ent: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/copyright.xml: -------------------------------------------------------------------------------- 1 | 2 | git-buildpackage, all associated scripts and programs, this manual, 3 | and all build scripts are Copyright © 2006-2017 Guido Günther. 4 | 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; Version 2 of the License. 9 | 10 | 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, please see 21 | <http://www.gnu.org/licenses/> 22 | 23 | -------------------------------------------------------------------------------- /docs/gbp.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Verdana, "Bitstream Vera Sans", sans-serif; 3 | font-size: large; 4 | } 5 | 6 | h1 { 7 | font-weight: normal; 8 | font-variant: small-caps; 9 | } 10 | 11 | h2, h3 { 12 | font-weight: normal; 13 | } 14 | 15 | a { 16 | color: #182C41 !important; 17 | font-weight: normal; 18 | transition: background-color 0.2s linear; 19 | } 20 | 21 | a:hover { 22 | background-color: #eef; 23 | } 24 | 25 | a[name] { 26 | background-color: #fff; 27 | } 28 | 29 | pre { 30 | background: #eef; 31 | border: solid 1px #aaf; 32 | padding: 0.5em; 33 | } 34 | 35 | pre.programlisting .command, pre.programlisting .filename, pre.programlisting .option, pre.programlisting .replaceable { 36 | background: none; 37 | } 38 | 39 | .command { 40 | font-style: italic; 41 | font-weight: normal; 42 | padding: 1px; 43 | } 44 | 45 | .filename { 46 | background: #eee; 47 | padding: 1px; 48 | } 49 | 50 | .option { 51 | background: rgba(150,150,150,0.2); 52 | padding: 1px; 53 | } 54 | 55 | .replaceable { 56 | background: rgba(150,150,150,0.2); 57 | padding: 1px; 58 | } 59 | 60 | table.variablelist { 61 | border: none; 62 | } 63 | 64 | .variablelist th,td { 65 | border: solid 1px #ddd; 66 | } 67 | 68 | div.book div.toc { 69 | background: url("gbp.svg") no-repeat; 70 | background-position: center; 71 | } 72 | 73 | div .titlepage table p.title { 74 | font-size: 300%; 75 | font-weight: normal; 76 | margin: 0.5em; 77 | } 78 | 79 | body.chapter table.navigation th { 80 | font-weight: normal; 81 | margin: 0.5em; 82 | } 83 | 84 | body.appendix table.navigation th { 85 | font-weight: normal; 86 | margin: 0.5em; 87 | } 88 | 89 | body.refentry table.navigation th { 90 | font-weight: normal; 91 | margin: 0.5em; 92 | } 93 | 94 | body.refentry code.option, body.refentry tt.replaceable, body.refentry tt.filename { 95 | background: none; 96 | } 97 | 98 | table.warning { 99 | border-style: solid; 100 | border-width: 5px; 101 | border-collapse: collapse; 102 | background: rgba(252, 175, 62, 0.1); 103 | border-color: rgba(252, 175, 62, 0.2); 104 | } 105 | 106 | table.warning td { 107 | border-width: 2px; 108 | border-color: rgba(252, 175, 62, 0.2); 109 | } 110 | 111 | table.footnotes td { 112 | border: none; 113 | } 114 | 115 | div.mediaobject { 116 | background: #f5f5f5; 117 | border-width: 2px; 118 | border-color: lightgrey; 119 | border-style: solid; 120 | } 121 | 122 | div.mediaobject img { 123 | margin-left: auto; 124 | margin-right: auto; 125 | display: block; 126 | padding: 5px 0px 0px 0px; 127 | } 128 | 129 | div.mediaobject p { 130 | text-align: center; 131 | font-style: italic; 132 | } 133 | -------------------------------------------------------------------------------- /docs/images/pq-applied.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/docs/images/pq-applied.png -------------------------------------------------------------------------------- /docs/images/pq-export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/docs/images/pq-export.png -------------------------------------------------------------------------------- /docs/images/pq-rebase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/docs/images/pq-rebase.png -------------------------------------------------------------------------------- /docs/images/pq-time-machine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/docs/images/pq-time-machine.png -------------------------------------------------------------------------------- /docs/images/pq-unapplied.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/docs/images/pq-unapplied.png -------------------------------------------------------------------------------- /docs/man.gbp.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | %COMMON; 6 | 7 | %MANPAGES; 8 | ]> 9 | 10 | 11 | git-buildpackage Manual 12 | &man.gbp; 13 | &man.gbp.buildpackage; 14 | &man.gbp.buildpackage.rpm; 15 | &man.gbp.clone; 16 | &man.gbp.conf; 17 | &man.gbp.config; 18 | &man.gbp.config-files; 19 | &man.gbp.create.remote.repo; 20 | &man.gbp.dch; 21 | &man.gbp.exportorig; 22 | &man.gbp.importdsc; 23 | &man.gbp.importdscs; 24 | &man.gbp.importorig; 25 | &man.gbp.importref; 26 | &man.gbp.import.srpm; 27 | &man.gbp.pq; 28 | &man.gbp.pq.rpm; 29 | &man.gbp.pristine.tar; 30 | &man.gbp.pull; 31 | &man.gbp.push; 32 | &man.gbp.rpm.ch; 33 | &man.gbp.setup.gitattributes; 34 | &man.gbp.tag; 35 | 36 | -------------------------------------------------------------------------------- /docs/manpages/gbp-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | &dhemail; 5 |
6 | 7 | &dhfirstname; 8 | &dhsurname; 9 | 10 |
11 | 12 | gbp-config 13 | &dhsection; 14 | 15 | 16 | gbp-config 17 | Query configuration values 18 | 19 | 20 | 21 | &gbp-config; 22 | 23 | &man.common.options.synopsis; 24 | 25 | command.option 26 | command 27 | 28 | 29 | 30 | 31 | DESCRIPTION 32 | 33 | &gbp-config; prints values from the configuration files. It interpolates the 34 | value for option of 35 | command. 36 | 37 | 38 | 39 | OPTIONS 40 | 41 | &man.common.options.description; 42 | 43 | 44 | 45 | EXIT CODES 46 | 47 | When &gbp-config; finishes, it indicates success or failure with its exit code: 48 | 49 | 50 | 51 | 52 | 53 | Success. 54 | 55 | 56 | 57 | 58 | 59 | Failed to parse command line 60 | 61 | 62 | 63 | 64 | 65 | The value did not exist 66 | 67 | 68 | 69 | 70 | 71 | EXAMPLES 72 | Print the value that &gbp-buildpackage; 73 | would use: 74 | 75 | $ gbp config buildpackage.upstream-branch 76 | buildpackage.upstream-branch=upstream 77 | Print the values of all of &gbp-buildpackage; options 78 | 79 | $ gbp config buildpackage 80 | buildpackage.upstream-branch=upstream 81 | buildpackage.debian-branch=master 82 | ... 83 | 84 | 85 | &man.gbp.config-files; 86 | 87 | 88 | SEE ALSO 89 | 90 | 91 | 92 | 93 | 94 | AUTHOR 95 | 96 | &dhusername; &dhemail; 97 | 98 | 99 |
100 | -------------------------------------------------------------------------------- /docs/manpages/man.common-options.ent: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | [auto|on|off] 7 | COLOR_SCHEME 8 | " 9 | > 10 | 13 | 14 | 15 | 16 | Print version of the program, i.e. version of the git-buildpackage 17 | suite 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Verbose execution 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Print help and exit 36 | 37 | 38 | 39 | 40 | [auto|on|off] 41 | 42 | 43 | 44 | Whether to use colored output. 45 | 46 | 47 | 48 | 49 | COLOR_SCHEME 50 | 51 | 52 | 53 | Colors to use in output (when color is enabled). The format for 54 | COLOR_SCHEME is 55 | '<debug>:<info>:<warning>:<error>'. 56 | Numerical values and color names are accepted, empty fields imply 57 | the default color. For example, 58 | 'cyan:34::' would 59 | show debug messages in cyan, info messages in blue and other messages 60 | in default (i.e. warning and error messages in red). 61 | 62 | 63 | 64 | " 65 | > 66 | 67 | -------------------------------------------------------------------------------- /docs/manpages/man.conffiles.xml: -------------------------------------------------------------------------------- 1 | CONFIGURATION FILES 2 | Several gbp.conf files are parsed 3 | to set defaults for the above command-line arguments. See the 4 | manpage for details. 5 | -------------------------------------------------------------------------------- /docs/manpages/man.seealso.xml: -------------------------------------------------------------------------------- 1 | 2 | debuild 3 | 1 4 | , 5 | 6 | git 7 | 1 8 | , 9 | 10 | pristine-tar 11 | 1 12 | , 13 | 14 | The Git-Buildpackage Manual 15 | -------------------------------------------------------------------------------- /docs/manpages/manpages.ent: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | %COMMON.OPTIONS; 28 | -------------------------------------------------------------------------------- /docs/manual.xml: -------------------------------------------------------------------------------- 1 | 4 | %COMMON; 5 | 6 | %VERSION; 7 | 8 | %MANPAGES; 9 | 10 | %CHAPTERS; 11 | 12 | ]> 13 | 14 | 15 | 16 | Building Debian Packages with git-buildpackage 17 | &dhfirstname; &dhsurname; 18 |
&dhemail;
19 | Version: &gbp-version; 20 |
21 | 22 | &ch.intro; 23 | &ch.import; 24 | &ch.building; 25 | &ch.patches; 26 | &ch.releases; 27 | &ch.cfgfile; 28 | &ch.special; 29 | 30 | 31 | Command Reference 32 | &man.gbp; 33 | &man.gbp.buildpackage; 34 | &man.gbp.clone; 35 | &man.gbp.config; 36 | &man.gbp.create.remote.repo; 37 | &man.gbp.dch; 38 | &man.gbp.exportorig; 39 | &man.gbp.importdsc; 40 | &man.gbp.importdscs; 41 | &man.gbp.importorig; 42 | &man.gbp.importref; 43 | &man.gbp.pq; 44 | &man.gbp.pristine.tar; 45 | &man.gbp.pull; 46 | &man.gbp.push; 47 | &man.gbp.tag; 48 | &man.gbp.conf; 49 | &man.gbp.buildpackage.rpm; 50 | &man.gbp.import.srpm; 51 | &man.gbp.pq.rpm; 52 | &man.gbp.rpm.ch; 53 | 54 | 55 | Copyright 56 | &gbp.copyright; 57 | 58 |
59 | 60 | -------------------------------------------------------------------------------- /docs/po/po4a.cfg: -------------------------------------------------------------------------------- 1 | [po_directory] po/ 2 | 3 | [options] --master-charset UTF-8 --keep 0 4 | 5 | [type: docbook] manual.xml $lang:_gen/$lang/manual.xml 6 | [type: docbook] copyright.xml $lang:_gen/$lang/copyright.xml 7 | 8 | [type: docbook] chapters/building.xml $lang:_gen/$lang/chapters/building.xml 9 | [type: docbook] chapters/cfgfile.xml $lang:_gen/$lang/chapters/cfgfile.xml 10 | [type: docbook] chapters/import.xml $lang:_gen/$lang/chapters/import.xml 11 | [type: docbook] chapters/intro.xml $lang:_gen/$lang/chapters/intro.xml 12 | [type: docbook] chapters/patches.xml $lang:_gen/$lang/chapters/patches.xml 13 | [type: docbook] chapters/releases.xml $lang:_gen/$lang/chapters/releases.xml 14 | [type: docbook] chapters/special.xml $lang:_gen/$lang/chapters/special.xml 15 | 16 | [type: docbook] manpages/gbp-buildpackage-rpm.xml $lang:_gen/$lang/manpages/gbp-buildpackage-rpm.xml 17 | [type: docbook] manpages/gbp-buildpackage.xml $lang:_gen/$lang/manpages/gbp-buildpackage.xml 18 | [type: docbook] manpages/gbp-clone.xml $lang:_gen/$lang/manpages/gbp-clone.xml 19 | [type: docbook] manpages/gbp-config.xml $lang:_gen/$lang/manpages/gbp-config.xml 20 | [type: docbook] manpages/gbp.conf.xml $lang:_gen/$lang/manpages/gbp.conf.xml 21 | [type: docbook] manpages/gbp-create-remote-repo.xml $lang:_gen/$lang/manpages/gbp-create-remote-repo.xml 22 | [type: docbook] manpages/gbp-dch.xml $lang:_gen/$lang/manpages/gbp-dch.xml 23 | [type: docbook] manpages/gbp-export-orig.xml $lang:_gen/$lang/manpages/gbp-export-orig.xml 24 | [type: docbook] manpages/gbp-import-dscs.xml $lang:_gen/$lang/manpages/gbp-import-dscs.xml 25 | [type: docbook] manpages/gbp-import-dsc.xml $lang:_gen/$lang/manpages/gbp-import-dsc.xml 26 | [type: docbook] manpages/gbp-import-orig.xml $lang:_gen/$lang/manpages/gbp-import-orig.xml 27 | [type: docbook] manpages/gbp-import-ref.xml $lang:_gen/$lang/manpages/gbp-import-ref.xml 28 | [type: docbook] manpages/gbp-import-srpm.xml $lang:_gen/$lang/manpages/gbp-import-srpm.xml 29 | [type: docbook] manpages/gbp-pq-rpm.xml $lang:_gen/$lang/manpages/gbp-pq-rpm.xml 30 | [type: docbook] manpages/gbp-pq.xml $lang:_gen/$lang/manpages/gbp-pq.xml 31 | [type: docbook] manpages/gbp-pristine-tar.xml $lang:_gen/$lang/manpages/gbp-pristine-tar.xml 32 | [type: docbook] manpages/gbp-pull.xml $lang:_gen/$lang/manpages/gbp-pull.xml 33 | [type: docbook] manpages/gbp-push.xml $lang:_gen/$lang/manpages/gbp-push.xml 34 | [type: docbook] manpages/gbp-rpm-ch.xml $lang:_gen/$lang/manpages/gbp-rpm-ch.xml 35 | [type: docbook] manpages/gbp-setup-gitattributes.xml $lang:_gen/$lang/manpages/gbp-setup-gitattributes.xml 36 | [type: docbook] manpages/gbp-tag.xml $lang:_gen/$lang/manpages/gbp-tag.xml 37 | [type: docbook] manpages/gbp.xml $lang:_gen/$lang/manpages/gbp.xml 38 | [type: docbook] manpages/man.conffiles.xml $lang:_gen/$lang/manpages/man.conffiles.xml 39 | [type: docbook] manpages/man.seealso.xml $lang:_gen/$lang/manpages/man.seealso.xml 40 | -------------------------------------------------------------------------------- /examples/README.source: -------------------------------------------------------------------------------- 1 | This package is maintained with git-buildpackage(1). It follows DEP-14 2 | for branch naming (e.g. using debian/latest for the current version 3 | in Debian unstable). 4 | 5 | It uses pristine-tar(1) to store enough information in git to generate 6 | bit identical tarballs when building the package without having 7 | downloaded an upstream tarball first. 8 | 9 | When working with patches it is recommended to use "gbp pq import" to 10 | import the patches, modify the source and then use "gbp pq export 11 | --commit" to commit the modifications. 12 | 13 | The changelog is generated using "gbp dch" so if you submit any 14 | changes don't bother to add changelog entries but rather provide 15 | a nice git commit message that can then end up in the changelog. 16 | 17 | It is recommended to build the package with pbuilder using: 18 | 19 | gbp buildpackage --git-pbuilder 20 | 21 | For information on how to set up a pbuilder environment see the 22 | git-pbuilder(1) manpage. In short: 23 | 24 | DIST=sid git-pbuilder create 25 | gbp clone 26 | cd 27 | gbp buildpackage --git-pbuilder 28 | 29 | -- Guido Günther , Wed, 2 Dec 2015 18:51:15 +0100 30 | -------------------------------------------------------------------------------- /examples/gbp-configure-unpatched-source: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | # Setup dpkg-source and git to unpatch the source after the build and ignore 5 | # the .pc directory. 6 | 7 | GIT_EXCLUDE=.git/info/exclude 8 | LOCAL_OPTIONS=debian/source/local-options 9 | 10 | help () 11 | { 12 | cat << EOF >/dev/stdout 13 | 14 | Modifies "$LOCAL_OPTIONS" and "$GIT_EXCLUDE" 15 | to ignore .pc and unpatch the source after the build. 16 | 17 | EOF 18 | 19 | exit $1 20 | } 21 | 22 | 23 | case $1 in 24 | -h|--help) 25 | help 0 26 | ;; 27 | esac 28 | 29 | 30 | if [ ! -d .git ]; then 31 | echo "Not the top of a git repository - aborting." 32 | help 1 33 | fi 34 | 35 | if ! grep -qs '^3.*\(quilt\)' debian/source/format; then 36 | echo "Not a source format 3 (quilt) package - aborting." 37 | help 1 38 | fi 39 | 40 | if ! grep -qs '^unapply-patches' $LOCAL_OPTIONS; then 41 | echo "Setting unapply-patches in $LOCAL_OPTIONS" 42 | echo "unapply-patches" >> $LOCAL_OPTIONS 43 | git add $LOCAL_OPTIONS 44 | git commit -m "Unapply patches from source" $LOCAL_OPTIONS 45 | else 46 | echo "unapply-patches already configured" 47 | fi 48 | 49 | if ! grep -qs "^\.pc/" $GIT_EXCLUDE; then 50 | echo "Adding .pc/ to $GIT_EXCLUDE" 51 | echo ".pc/" >> $GIT_EXCLUDE 52 | else 53 | echo "$GIT_EXCLUDE already configured" 54 | fi 55 | -------------------------------------------------------------------------------- /examples/gbp-svn-tag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Helper script to tag a version in SVN if using git-svn(1) 4 | 5 | DIST=$(dpkg-parsechangelog | awk "/^Distribution:/{ print \$2; }") 6 | VERSION=$(dpkg-parsechangelog | awk "/^Version:/{ print \$2; }") 7 | PKG=$(dpkg-parsechangelog | awk "/^Source:/{ print \$2; }") 8 | 9 | 10 | if [ "$DIST" = "UNRELEASED" ]; then 11 | echo "Distribution is unreleased" 12 | exit 1 13 | elif [ -z "$VERSION" ]; then 14 | echo "Can't read package version" 15 | exit 1 16 | fi 17 | 18 | git svn tag -m"Tagging $PKG ($VERSION)" $VERSION 19 | 20 | -------------------------------------------------------------------------------- /examples/gbp-try-ff: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Try to update a package to a new upstream version 4 | 5 | set -e 6 | 7 | DB=$(gbp config buildpackage.debian-branch | sed 's/\(.*debian-branch=\)\(.*\)/\2/') 8 | MAINTAINER=$(dpkg-parsechangelog -SMaintainer) 9 | SOURCE=$(dpkg-parsechangelog -SSource) 10 | OLD_VERSION=$(dpkg-parsechangelog -SVersion) 11 | 12 | git checkout "${DB}" 13 | gbp pq import --force 14 | git checkout "${DB}" 15 | 16 | set +e 17 | gbp import-orig --uscan --no-interactive --no-pristine-tar 18 | ret=$? 19 | set -e 20 | # no new version found 21 | if [ $ret = 4 ]; then 22 | exit 0 23 | # all other errors 24 | elif [ $ret != 0 ]; then 25 | exit $ret 26 | fi 27 | 28 | if ! gbp pq rebase; then 29 | echo "Automatic rebase failed" 30 | git rebase --abort 31 | exit 1 32 | fi 33 | 34 | gbp pq export --commit 35 | gbp dch -S -a 36 | 37 | NEW_VERSION=$(dpkg-parsechangelog -SVersion) 38 | git commit -m"Snapshot build of ${SOURCE} $NEW_VERSION" debian/changelog 39 | 40 | gbp buildpackage --git-pbuilder \ 41 | --git-no-pristine-tar \ 42 | --git-postbuild='lintian $GBP_CHANGES_FILE' \ 43 | -nc \ 44 | ${GBP_BUILDPACKAGE_ARGS} 45 | 46 | MSG="Fast forward of ${SOURCE} from ${OLD_VERSION} to ${NEW_VERSION} successful" 47 | echo "${MSG}" 48 | MAILADDR=$(echo $MAINTAINER | sed -e 's/.*<\(.*\)>/\1/') 49 | echo "$MSG" | mail -s "Update of ${SOURCE} to ${NEW_VERSION}" "${MAILADDR}" 50 | -------------------------------------------------------------------------------- /examples/gbp-upload: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Tag, upload to the Debian archive and push to the remote 4 | 5 | set -e 6 | set -u 7 | 8 | REMOTE=salsa+rw 9 | DEBS_DIR=.. 10 | 11 | if gbp config upload.remote; then 12 | REMOTE="$(gbp config upload.remote)" 13 | fi 14 | 15 | if [ -n "$(gbp config buildpackage.export-dir)" ] ; then 16 | DEBS_DIR="$(gbp config buildpackage.export-dir)" 17 | fi 18 | 19 | VERSION="$(dpkg-parsechangelog -S Version)" 20 | SOURCE="$(dpkg-parsechangelog -S Source)" 21 | CHANGES="${DEBS_DIR}/${SOURCE}_${VERSION}_source.changes" 22 | 23 | if ! git remote show "${REMOTE}" >/dev/null 2>&1; then 24 | echo "Failed to access ${REMOTE}." 25 | exit 1 26 | fi 27 | 28 | less --quit-at-eof "${CHANGES}" 29 | echo "Hit to upload, -C to quit" 30 | read -r VAL 31 | 32 | echo "Signing tag and built artifacts" 33 | gbp tag 34 | debsign --debs-dir "${DEBS_DIR}" -S 35 | 36 | echo "Uploading ${CHANGES}" 37 | dput $@ "${CHANGES}" 38 | echo "Pushing to ${REMOTE}" 39 | gbp push "${REMOTE}" 40 | -------------------------------------------------------------------------------- /examples/jenkins-scratchbuilder: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # - Use "execute shell" step in Jenkins like 4 | # 5 | # export ARCH=i386 6 | # export DIST=sid 7 | # jenkins-scratchbuilder 8 | # 9 | # - jenkins must be be able to invoke cowbuilder/pbuilder via sudo: 10 | # 11 | # %pbuilder ALL = SETENV: NOPASSWD: /usr/sbin/cowbuilder, /usr/sbin/pbuilder 12 | # 13 | # - It assumes you checked out the sources into scratchbuild/ 14 | 15 | set +e 16 | 17 | # Remove old build artifacts from workspace 18 | rm -f *.deb *.changes *.build *.dsc 19 | 20 | # We assume jenkins was told to checkout into a specific subdir 21 | # named scratchbuild 22 | cd scratchbuild/ 23 | 24 | # Make sure we have an up-to-date cowbuilder environment 25 | # Note that git-pbuilder will pick up $DIST and $ARCH from the environment 26 | [ -d /var/cache/pbuilder/base.cow ] || git-pbuilder create 27 | git-pbuilder update 28 | 29 | # Cleanup any leftovers 30 | git clean -dfx 31 | 32 | # Reset the changelog 33 | git checkout -f debian/changelog 34 | 35 | # Create a monotonically increasing changelog by including the build number 36 | gbp dch -S -a --ignore-branch --snapshot-number=${BUILD_NUMBER} 37 | 38 | # Build the package 39 | [ -z ARCH ] || GBP_OPTS="$GBP_OPTS --git-arch=$ARCH" 40 | [ -z DIST ] || GBP_OPTS="$GBP_OPTS --git-dist=$DIST" 41 | gbp buildpackage ${GBP_OPTS} --git-ignore-branch --git-pbuilder --git-cleaner=/bin/true --git-ignore-new --git-pristine-tar -b 42 | -------------------------------------------------------------------------------- /examples/wrap_cl.py: -------------------------------------------------------------------------------- 1 | # Simple changelog entry formatter 2 | # 3 | # It simply uses the built in formatter and linewraps the text 4 | # 5 | # Use git-dch --customizations=/usr/share/doc/git-buildpackage/examples/wrap_cl.py 6 | # or set it via gbp.conf 7 | 8 | import textwrap 9 | import gbp.dch 10 | 11 | 12 | def format_changelog_entry(commit_info, options, last_commit=False): 13 | entry = gbp.dch.format_changelog_entry(commit_info, options, last_commit) 14 | if entry: 15 | return textwrap.wrap(" ".join(entry)) 16 | -------------------------------------------------------------------------------- /examples/zeitgeist-git.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python3 2 | # vim: set fileencoding=utf-8 : 3 | # 4 | # (C) 2010 Guido Günther 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | # 19 | # Simple Zeitgeist Git data source 20 | 21 | """Post-commit hook to submit the commit to Zeitgeist (http://www.zeitgeist-project.com) 22 | 23 | copy as post-commit to 24 | 25 | .git/hooks/post-commit 26 | 27 | in existing repositories or to 28 | 29 | /usr/share/git-core/templates 30 | 31 | so it gets used for new ones. 32 | """ 33 | 34 | 35 | import os 36 | import subprocess 37 | import sys 38 | import time 39 | 40 | CLIENT = None 41 | 42 | try: 43 | from zeitgeist.client import ZeitgeistClient 44 | from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation 45 | except ImportError: 46 | pass 47 | else: 48 | try: 49 | CLIENT = ZeitgeistClient() 50 | except RuntimeError as e: 51 | print("Unable to connect to Zeitgeist, won't send events. Reason: '%s'" % e) 52 | 53 | 54 | def get_repo(): 55 | """Get uri of remote repository and its name""" 56 | repo = None 57 | uri = subprocess.Popen(['git', 'config', '--get', 'remote.origin.url'], 58 | stdout=subprocess.PIPE).communicate()[0] 59 | 60 | if uri: 61 | uri = uri.strip().decode(sys.getfilesystemencoding()) 62 | if '/' in uri: 63 | sep = '/' 64 | else: 65 | sep = ':' 66 | try: 67 | repo = uri.rsplit(sep, 1)[1] 68 | except IndexError: # no known separator 69 | repo = uri 70 | repo = repo.rsplit(u'.git', 1)[0] 71 | return repo, uri 72 | 73 | 74 | def main(argv): 75 | if not CLIENT: 76 | return 77 | 78 | interpretation = Interpretation.MODIFY_EVENT.uri 79 | 80 | # FIXME: I'd be great if zeitgeist would allow for more detail: 81 | # * branch 82 | # * log summary (git log -1 --format=%s HEAD) 83 | curdir = os.path.abspath(os.curdir).decode(sys.getfilesystemencoding()) 84 | uri = u"file://%s" % curdir 85 | 86 | repo, origin = get_repo() 87 | if not repo: 88 | repo = curdir.rsplit('/', 1)[1] 89 | origin = uri 90 | 91 | subject = Subject.new_for_values( 92 | uri=uri, 93 | interpretation=Interpretation.DOCUMENT.TEXT_DOCUMENT.PLAIN_TEXT_DOCUMENT.SOURCE_CODE.uri, 94 | manifestation=Manifestation.FILE_DATA_OBJECT.uri, 95 | text=repo, 96 | origin=origin) 97 | event = Event.new_for_values( 98 | timestamp=int(time.time() * 1000), 99 | interpretation=interpretation, 100 | manifestation=Manifestation.USER_ACTIVITY.uri, 101 | actor="application://gitg.desktop", 102 | subjects=[subject]) 103 | CLIENT.insert_event(event) 104 | 105 | 106 | if __name__ == '__main__': 107 | main(sys.argv) 108 | -------------------------------------------------------------------------------- /gbp/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2006,2007,2008 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """The various things needed by git-buildpackage and friends""" 18 | 19 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 20 | -------------------------------------------------------------------------------- /gbp/deb/control.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012 Daniel Dehennin 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """A Debian Control file""" 18 | 19 | import email 20 | import os 21 | 22 | 23 | class NoControlError(Exception): 24 | """No control found""" 25 | pass 26 | 27 | 28 | class ParseControlError(Exception): 29 | """Problem parsing control""" 30 | pass 31 | 32 | 33 | class Control(object): 34 | """A Debian control""" 35 | 36 | def __init__(self, contents=None, filename="debian/control"): 37 | """ 38 | Parse an existing control file. 39 | 40 | @param contents: content of a control file 41 | @type contents: C{str} 42 | @param filename: name of the control file 43 | @type filename: C{str} 44 | @return: Control object 45 | @rtype: C{gbp.deb.control.Control} object 46 | """ 47 | if contents: 48 | control = email.message_from_string(contents) 49 | else: 50 | if not os.access(filename, os.F_OK): 51 | raise NoControlError("Control file %s does not exist" % filename) 52 | 53 | with open(filename) as f: 54 | control = email.message_from_file(f) 55 | 56 | if not control.items(): 57 | raise ParseControlError("Empty or invalid control file or contents") 58 | 59 | self._control = control 60 | self.filename = filename 61 | 62 | def __getitem__(self, item): 63 | return self._control[item] 64 | 65 | def __setitem__(self, item, value): 66 | self._control[item] = value 67 | 68 | @property 69 | def name(self): 70 | """The name of the package""" 71 | return self._control['Source'] 72 | 73 | @property 74 | def section(self): 75 | """The section of the package""" 76 | return self._control['Section'] 77 | 78 | @property 79 | def priority(self): 80 | """The priority of the package""" 81 | return self._control['Priority'] 82 | -------------------------------------------------------------------------------- /gbp/deb/pristinetar.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Handle checkin and checkout of archives from the pristine-tar branch""" 18 | 19 | from gbp.pkg.compressor import Compressor 20 | from gbp.pkg.pristinetar import PristineTar 21 | from gbp.deb import DebianPkgPolicy 22 | 23 | 24 | class DebianPristineTar(PristineTar): 25 | """The pristine-tar branch in a Debian git repository""" 26 | def has_commit(self, package, version, comp_type=None): 27 | """ 28 | Do we have a pristine-tar commit for package I{package} at version 29 | {version} with compression type I{comp_type}? 30 | 31 | @param package: the package to look for 32 | @type package: C{str} 33 | @param version: the upstream version to look for 34 | @type version: C{str} 35 | @param comp_type: the compression type 36 | @type comp_type: C{str} 37 | """ 38 | if not comp_type: 39 | ext = r'\w\+' 40 | else: 41 | ext = Compressor.Exts[comp_type] 42 | 43 | name_regexp = r'%s_%s\.orig\.tar\.%s' % (package, version, ext) 44 | 45 | return super(DebianPristineTar, self).has_commit(name_regexp) 46 | 47 | def checkout(self, package, version, comp_type, output_dir, component=None, 48 | quiet=False, signature=False): 49 | """ 50 | Checkout the orig tarball for package I{package} of I{version} and 51 | compression type I{comp_type} to I{output_dir} 52 | 53 | @param package: the package to generate the orig tarball for 54 | @type package: C{str} 55 | @param version: the version to check generate the orig tarball for 56 | @type version: C{str} 57 | @param comp_type: the compression type of the tarball 58 | @type comp_type: C{str} 59 | @param output_dir: the directory to put the tarball into 60 | @type output_dir: C{str} 61 | """ 62 | signaturefile = None 63 | name = DebianPkgPolicy.build_tarball_name(package, 64 | version, 65 | comp_type, 66 | output_dir, 67 | component=component) 68 | if signature: 69 | signaturefile = DebianPkgPolicy.build_signature_name(package, 70 | version, 71 | comp_type, 72 | output_dir, 73 | component=component) 74 | super(DebianPristineTar, self).checkout(name, 75 | quiet=quiet, 76 | signaturefile=signaturefile) 77 | -------------------------------------------------------------------------------- /gbp/deb/upstreamsource.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2013 Intel Corporation 4 | # (C) 2016 Guido Günther 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | """Debian-specific upstream sources""" 19 | 20 | from gbp.pkg import UpstreamSource 21 | from gbp.deb.policy import DebianPkgPolicy 22 | import gbp.command_wrappers 23 | 24 | import os 25 | import shutil 26 | import tempfile 27 | 28 | 29 | class DebianUpstreamSource(UpstreamSource): 30 | """Upstream source class for Debian""" 31 | def __init__(self, name, unpacked=None, sig=None): 32 | super(DebianUpstreamSource, self).__init__(name, 33 | unpacked=unpacked, 34 | sig=sig, 35 | pkg_policy=DebianPkgPolicy) 36 | 37 | 38 | class DebianAdditionalTarball(DebianUpstreamSource): 39 | """Upstream source class for additional tarballs""" 40 | def __init__(self, name, component, unpacked=None, sig=None): 41 | self.component = component 42 | super(DebianAdditionalTarball, self).__init__(name, 43 | unpacked=unpacked, 44 | sig=sig) 45 | 46 | def unpack(self, dest, filters): 47 | """ 48 | Unpack the additional tarball into {dir} naming it 49 | I{component}. Apply filters during unpack. 50 | 51 | @param dir: the main tarball dir 52 | @param filters: filters to apply 53 | 54 | We can't simply use unpack since we need to remove any preexisting dirs and 55 | name the target directory after the component name. 56 | """ 57 | olddir = os.path.abspath(os.path.curdir) 58 | tmpdir = None 59 | try: 60 | tmpdir = os.path.abspath(tempfile.mkdtemp(dir=os.path.join(dest, '..'))) 61 | super(DebianAdditionalTarball, self).unpack(tmpdir, filters) 62 | 63 | newdest = os.path.join(dest, self.component) 64 | if os.path.exists(newdest): 65 | shutil.rmtree(newdest) 66 | shutil.move(self.unpacked, newdest) 67 | finally: 68 | os.chdir(olddir) 69 | if tmpdir is not None: 70 | gbp.command_wrappers.RemoveTree(tmpdir)() 71 | 72 | 73 | type DebianUpstreamTarballList = list[DebianUpstreamSource | DebianAdditionalTarball] 74 | -------------------------------------------------------------------------------- /gbp/errors.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2006,2007,2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Errors raised in gbp commands""" 18 | 19 | 20 | class GbpError(Exception): 21 | """Generic exception raised in git-buildpackage commands""" 22 | pass 23 | 24 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 25 | -------------------------------------------------------------------------------- /gbp/format.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2014 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Format a message""" 18 | 19 | from gbp.errors import GbpError 20 | 21 | 22 | def format_str(msg, args): 23 | """ 24 | Format a string with the given dict. Be a bit more verbose than 25 | default python about the error cause. 26 | 27 | >>> format_str("%(foo)", {}) 28 | Traceback (most recent call last): 29 | ... 30 | gbp.errors.GbpError: Failed to format %(foo): Missing value 'foo' in {} 31 | >>> format_str("%(foo)", {'foo': 'bar'}) 32 | Traceback (most recent call last): 33 | ... 34 | gbp.errors.GbpError: Failed to format %(foo) with {'foo': 'bar'}: incomplete format 35 | >>> format_str("A %(foo)s is a %(bar)s", {'foo': 'dog', 'bar': 'mamal'}) 36 | 'A dog is a mamal' 37 | """ 38 | try: 39 | return msg % args 40 | except ValueError as e: 41 | raise GbpError("Failed to format %s with %s: %s" % (msg, args, e)) 42 | except KeyError as e: 43 | raise GbpError("Failed to format %s: Missing value %s in %s" % 44 | (msg, e, args)) 45 | -------------------------------------------------------------------------------- /gbp/git/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2006,2007,2008,2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Accessing Git from python""" 18 | 19 | import calendar 20 | import dateutil.parser 21 | 22 | from gbp.git.modifier import GitModifier # noqa: F401 23 | from gbp.git.commit import GitCommit # noqa: F401 24 | from gbp.git.errors import GitError # noqa: F401 25 | from gbp.git.repository import ( # noqa: F401 26 | GitRepository, GitRepositoryError) 27 | from gbp.git.fastimport import FastImport # noqa: F401 28 | from gbp.git.args import GitArgs # noqa: F401 29 | from gbp.git.vfs import GitVfs # noqa: F401 30 | 31 | 32 | def rfc822_date_to_git(rfc822_date, fuzzy=False): 33 | """Parse a date in RFC822 format, and convert to a 'seconds tz' C{str}ing. 34 | 35 | >>> rfc822_date_to_git('Thu, 1 Jan 1970 00:00:01 +0000') 36 | '1 +0000' 37 | >>> rfc822_date_to_git('Thu, 20 Mar 2008 01:12:57 -0700') 38 | '1206000777 -0700' 39 | >>> rfc822_date_to_git('Sat, 5 Apr 2008 17:01:32 +0200') 40 | '1207407692 +0200' 41 | >>> rfc822_date_to_git('So, 26 Feb 1998 8:50:00 +0100', fuzzy=True) 42 | '888479400 +0100' 43 | """ 44 | d = dateutil.parser.parse(rfc822_date, fuzzy=fuzzy) 45 | seconds = calendar.timegm(d.utctimetuple()) 46 | tz = d.strftime("%z") 47 | return '%d %s' % (seconds, tz) 48 | 49 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 50 | -------------------------------------------------------------------------------- /gbp/git/args.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """ 18 | Git command argument handling helpers 19 | """ 20 | 21 | import collections.abc 22 | 23 | 24 | class GitArgs(object): 25 | """ 26 | Handle arguments to git commands 27 | 28 | >>> GitArgs('-h', '--no-foo').args 29 | ['-h', '--no-foo'] 30 | >>> GitArgs('-n', 123).args 31 | ['-n', '123'] 32 | >>> GitArgs().add('--more-foo', '--less-bar').args 33 | ['--more-foo', '--less-bar'] 34 | >>> GitArgs().add(['--foo', '--bar']).args 35 | ['--foo', '--bar'] 36 | >>> GitArgs().add_cond(1 > 2, '--opt', '--no-opt').args 37 | ['--no-opt'] 38 | >>> GitArgs().add_true(True, '--true').args 39 | ['--true'] 40 | >>> GitArgs().add_false(True, '--true').args 41 | [] 42 | >>> GitArgs().add_false(False, '--false').args 43 | ['--false'] 44 | """ 45 | 46 | def __init__(self, *args): 47 | self._args = [] 48 | self.add(args) 49 | 50 | @property 51 | def args(self): 52 | return self._args 53 | 54 | def add(self, *args): 55 | """ 56 | Add arguments to argument list 57 | """ 58 | for arg in args: 59 | if isinstance(arg, str): 60 | self._args.append(arg) 61 | elif isinstance(arg, collections.abc.Iterable): 62 | for i in iter(arg): 63 | self._args.append(str(i)) 64 | else: 65 | self._args.append(str(arg)) 66 | 67 | return self 68 | 69 | def add_true(self, condition, *args): 70 | """ 71 | Add I{args} if I{condition} is C{True} 72 | 73 | @param condition: the condition to test 74 | @type condition: C{bool} 75 | @param args: arguments to add 76 | """ 77 | if condition: 78 | self.add(*args) 79 | return self 80 | 81 | def add_false(self, condition, *args): 82 | """ 83 | Add I{args} if I{condition} is C{False} 84 | 85 | @param condition: the condition to test 86 | @type condition: C{bool} 87 | @param args: arguments to add 88 | """ 89 | self.add_true(not condition, *args) 90 | return self 91 | 92 | def add_cond(self, condition, opt, noopt=[]): 93 | """ 94 | Add option I{opt} to I{alist} if I{condition} is C{True} 95 | else add I{noopt}. 96 | 97 | @param condition: condition 98 | @type condition: C{bool} 99 | @param opt: option to add if I{condition} is C{True} 100 | @type opt: C{str} or C{list} 101 | @param noopt: option to add if I{condition} is C{False} 102 | @type noopt: C{str} or C{list} 103 | """ 104 | if condition: 105 | self.add(opt) 106 | else: 107 | self.add(noopt) 108 | return self 109 | -------------------------------------------------------------------------------- /gbp/git/commit.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Git commit class and helpers""" 18 | 19 | import re 20 | 21 | 22 | class GitCommit(object): 23 | """A git commit""" 24 | sha1_re = re.compile(r'[0-9a-f]{40}$') 25 | 26 | @staticmethod 27 | def is_sha1(value): 28 | """ 29 | Is I{value} a valid 40 digit SHA1? 30 | 31 | >>> GitCommit.is_sha1('asdf') 32 | False 33 | >>> GitCommit.is_sha1('deadbeef') 34 | False 35 | >>> GitCommit.is_sha1('17975594b2d42f2a3d144a9678fdf2c2c1dd96a0') 36 | True 37 | >>> GitCommit.is_sha1('17975594b2d42f2a3d144a9678fdf2c2c1dd96a0toolong') 38 | False 39 | 40 | @param value: the value to check 41 | @type value: C{str} 42 | @return: C{True} if I{value} is a 40 digit SHA1, C{False} otherwise. 43 | @rtype: C{bool} 44 | """ 45 | return True if GitCommit.sha1_re.match(value) else False 46 | -------------------------------------------------------------------------------- /gbp/git/errors.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Git base error exception""" 18 | 19 | 20 | class GitError(Exception): 21 | """Exception thrown by Git related classes""" 22 | pass 23 | -------------------------------------------------------------------------------- /gbp/git/vfs.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2013 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Make blobs in a git repository accessible as file like objects""" 18 | 19 | import io 20 | from gbp.git.repository import GitRepositoryError 21 | 22 | 23 | class GitVfs(object): 24 | 25 | class _File(object): 26 | """ 27 | A file like object representing a file in git 28 | 29 | @todo: We don't support any byte ranges yet. 30 | """ 31 | def __init__(self, content, binary=False): 32 | self._iter = iter 33 | if binary: 34 | self._data = io.BytesIO(content) 35 | else: 36 | try: 37 | self._data = io.StringIO(content.decode()) 38 | except UnicodeDecodeError: 39 | self._data = io.StringIO(content.decode("iso-8859-1")) 40 | 41 | def readline(self): 42 | return self._data.readline() 43 | 44 | def readlines(self): 45 | return self._data.readlines() 46 | 47 | def read(self, size=None): 48 | return self._data.read(size) 49 | 50 | def close(self): 51 | return self._data.close() 52 | 53 | def __enter__(self): 54 | return self 55 | 56 | def __exit__(self, exc_type, exc_val, exc_tb): 57 | self.close() 58 | 59 | def __init__(self, repo, commitish=None): 60 | """ 61 | @param repo: the git repository to act on 62 | @param commitish: the commit-ish to act on 63 | """ 64 | self._repo = repo 65 | self._commitish = commitish or 'HEAD' 66 | 67 | def open(self, path, flags=None): 68 | flags = flags or 'r' 69 | 70 | for flag in flags: 71 | if flag not in ['r', 't', 'b']: 72 | raise NotImplementedError("Flag '%s' unsupported so far" % flag) 73 | try: 74 | return GitVfs._File(self._repo.show( 75 | "%s:%s" % (self._commitish, path)), 76 | True if 'b' in flags else False) 77 | except GitRepositoryError as e: 78 | raise OSError(e) 79 | -------------------------------------------------------------------------------- /gbp/notifications.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | 18 | import warnings 19 | 20 | notify_module = None 21 | 22 | 23 | def enable_notifications(): 24 | global notify_module 25 | 26 | with warnings.catch_warnings(): 27 | # Avoid GTK+ cannot open display warning: 28 | warnings.simplefilter("ignore") 29 | try: 30 | import notify2 # type: ignore 31 | notify_module = notify2 32 | except (ImportError, RuntimeError): 33 | return False 34 | 35 | try: 36 | return notify_module.init("git-buildpackage") 37 | except Exception: 38 | return False 39 | 40 | 41 | def build_msg(cp, success): 42 | summary = "Gbp %s" % ["failed", "successful"][success] 43 | msg = ("Build of %s %s %s" % 44 | (cp['Source'], cp['Version'], ["failed", "succeeded"][success])) 45 | 46 | return summary, msg 47 | 48 | 49 | def send_notification(summary, msg): 50 | n = notify_module.Notification(summary, msg) 51 | n.set_hint('transient', True) 52 | try: 53 | if not n.show(): 54 | return False 55 | except Exception: 56 | return False 57 | return True 58 | 59 | 60 | def notify(summary, message, notify_opt): 61 | """ 62 | Send a notifications 63 | @return: False on error 64 | """ 65 | 66 | if notify_opt.is_off(): 67 | return True 68 | 69 | enable = enable_notifications() 70 | if not enable: 71 | return [True, False][notify_opt.is_on()] 72 | 73 | return notify_opt.do(send_notification, summary, message) 74 | -------------------------------------------------------------------------------- /gbp/paths.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2017 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | "Helpers to handle paths" 18 | 19 | 20 | def to_bin(path): 21 | """Convert to binary if not already 22 | 23 | We want paths to be binary since we can't assume an encoding but 24 | it shall still be convenient to pass in unicode strings 25 | """ 26 | return path.encode() if not isinstance(path, bytes) else path 27 | -------------------------------------------------------------------------------- /gbp/pkg/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2006,2007 Guido Günther 4 | # (C) 2012 Intel Corporation 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | """Common functionality of the Debian/RPM package helpers""" 19 | 20 | from gbp.pkg.pkgpolicy import PkgPolicy # noqa: F401 21 | from gbp.pkg.compressor import Compressor # noqa: F401 22 | from gbp.pkg.archive import Archive # noqa: F401 23 | from gbp.pkg.upstreamsource import UpstreamSource # noqa: F401 24 | from gbp.pkg.pristinetar import PristineTar # noqa: F401 25 | -------------------------------------------------------------------------------- /gbp/pkg/archive.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2017 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | 18 | from .compressor import Compressor 19 | 20 | 21 | class Archive(object): 22 | # Supported archive formats 23 | Formats = ['tar', 'zip'] 24 | 25 | # Map combined file extensions to archive and compression format 26 | Ext_aliases = {'tgz': ('tar', 'gzip'), 27 | 'tbz2': ('tar', 'bzip2'), 28 | 'tlz': ('tar', 'lzma'), 29 | 'txz': ('tar', 'xz')} 30 | 31 | @staticmethod 32 | def parse_filename(filename): 33 | """ 34 | Given an filename return the basename (filename without the 35 | archive and compression extensions), archive format and 36 | compression method used. 37 | 38 | @param filename: the name of the file 39 | @type filename: string 40 | @return: tuple containing basename, archive format and compression method 41 | @rtype: C{tuple} of C{str} 42 | 43 | >>> Archive.parse_filename("abc.tar.gz") 44 | ('abc', 'tar', 'gzip') 45 | >>> Archive.parse_filename("abc.tar.bz2") 46 | ('abc', 'tar', 'bzip2') 47 | >>> Archive.parse_filename("abc.def.tbz2") 48 | ('abc.def', 'tar', 'bzip2') 49 | >>> Archive.parse_filename("abc.def.tar.xz") 50 | ('abc.def', 'tar', 'xz') 51 | >>> Archive.parse_filename("abc.zip") 52 | ('abc', 'zip', None) 53 | >>> Archive.parse_filename("abc.lzma") 54 | ('abc', None, 'lzma') 55 | >>> Archive.parse_filename("abc.tar.foo") 56 | ('abc.tar.foo', None, None) 57 | >>> Archive.parse_filename("abc") 58 | ('abc', None, None) 59 | """ 60 | (base_name, archive_fmt, compression) = (filename, None, None) 61 | 62 | # Split filename into pieces 63 | split = filename.split(".") 64 | if len(split) > 1: 65 | if split[-1] in Archive.Ext_aliases: 66 | base_name = ".".join(split[:-1]) 67 | (archive_fmt, compression) = Archive.Ext_aliases[split[-1]] 68 | elif split[-1] in Archive.Formats: 69 | base_name = ".".join(split[:-1]) 70 | (archive_fmt, compression) = (split[-1], None) 71 | else: 72 | for (c, ext) in Compressor.Exts.items(): 73 | if ext == split[-1]: 74 | base_name = ".".join(split[:-1]) 75 | compression = c 76 | if len(split) > 2 and split[-2] in Archive.Formats: 77 | base_name = ".".join(split[:-2]) 78 | archive_fmt = split[-2] 79 | 80 | return (base_name, archive_fmt, compression) 81 | -------------------------------------------------------------------------------- /gbp/pkg/compressor.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2017 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | 18 | 19 | class Compressor(object): 20 | # Map frequently used names of compression types to the internal ones: 21 | Aliases = {'bz2': 'bzip2', 22 | 'gz': 'gzip', } 23 | 24 | Opts = {'gzip': '-n', 25 | 'bzip2': '', 26 | 'lzma': '', 27 | 'xz': ''} 28 | 29 | Exts = {'gzip': 'gz', 30 | 'bzip2': 'bz2', 31 | 'lzma': 'lzma', 32 | 'xz': 'xz'} 33 | 34 | def __init__(self, type_, level=None): 35 | self._type = type_ 36 | self._level = int(level) if level not in [None, ''] else None 37 | 38 | def is_known(self): 39 | return self.type in self.Opts.keys() 40 | 41 | @property 42 | def type(self): 43 | return self._type 44 | 45 | @property 46 | def level(self): 47 | return self._level 48 | 49 | @property 50 | def _level_opt(self): 51 | return '-%d' % self.level if self.level is not None else '' 52 | 53 | @property 54 | def _more_opts(self): 55 | return self.Opts.get(self._type, '') 56 | 57 | def cmdline(self, stdout=True): 58 | """ 59 | >>> Compressor('gzip', level=9).cmdline() 60 | 'gzip -9 -n -c' 61 | >>> Compressor('gzip').cmdline(True) 62 | 'gzip -n -c' 63 | """ 64 | return "%s %s %s %s" % (self.type, self._level_opt, self._more_opts, 65 | "-c" if stdout else '') 66 | 67 | def __repr__(self): 68 | """ 69 | >>> Compressor('gzip').__repr__() 70 | "" 71 | >>> Compressor('gzip', 9).__repr__() 72 | "" 73 | """ 74 | level_str = "level=%s" % self.level if self.level is not None else '' 75 | return "" % (self.type, level_str) 76 | -------------------------------------------------------------------------------- /gbp/rpm/lib_rpm.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012 Intel Corporation 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Wrapper module for librpm""" 18 | 19 | import tempfile 20 | 21 | import gbp.log 22 | from gbp.rpm.policy import RpmPkgPolicy 23 | 24 | try: 25 | # Try to load special RPM lib to be used for GBP (only) 26 | librpm = __import__(RpmPkgPolicy.python_rpmlib_module_name) 27 | except ImportError: 28 | gbp.log.warn("Failed to import '%s' as rpm python module, using host's " 29 | "default rpm library instead" % 30 | RpmPkgPolicy.python_rpmlib_module_name) 31 | import rpm as librpm # type: ignore 32 | 33 | # Module initialization 34 | _rpmlog = tempfile.NamedTemporaryFile(mode='w+', prefix='gbp_rpmlog') 35 | _rpmlogfd = _rpmlog.file 36 | librpm.setVerbosity(librpm.RPMLOG_INFO) 37 | librpm.setLogFile(_rpmlogfd) 38 | 39 | 40 | def get_librpm_log(truncate=True): 41 | """Get rpmlib log output""" 42 | _rpmlogfd.seek(0) 43 | log = [line.strip() for line in _rpmlogfd.readlines()] 44 | if truncate: 45 | _rpmlogfd.truncate(0) 46 | return log 47 | -------------------------------------------------------------------------------- /gbp/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2013 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """The gbp commands""" 18 | -------------------------------------------------------------------------------- /gbp/scripts/common/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2013 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Parts shared between the deb and rpm commands""" 18 | 19 | import re 20 | import os 21 | import traceback 22 | from gbp.errors import GbpError 23 | from gbp.deb import DebianPkgPolicy 24 | from gbp.pkg import Archive 25 | from gbp.deb.upstreamsource import DebianAdditionalTarball 26 | 27 | 28 | class ExitCodes(object): 29 | ok = 0, 30 | failed = 1 # All other errors 31 | no_value = 2 # Value does not exist (gbp config only) 32 | parse_error = 3 # Failed to parse configuration file 33 | uscan_up_to_date = 4 # Uscan up to date (import-orig only) 34 | 35 | 36 | def maybe_debug_raise(): 37 | if 'raise' in os.getenv("GBP_DEBUG", '').split(','): 38 | raise 39 | 40 | 41 | def is_download(args): 42 | """ 43 | >>> is_download(["http://foo.example.com"]) 44 | True 45 | >>> is_download([]) 46 | False 47 | >>> is_download(["foo-1.1.orig.tar.gz"]) 48 | False 49 | """ 50 | if args and re.match("https?://", args[0]): 51 | return True 52 | return False 53 | 54 | 55 | # FIXME: this could become a method of DebianUpstreamSource 56 | def get_component_tarballs(name: str, 57 | version: str, 58 | tarball: str, 59 | components: list[str]) -> list[DebianAdditionalTarball]: 60 | """ 61 | Figure out the paths to the component tarballs based on the main 62 | tarball. 63 | """ 64 | tarballs = [] 65 | (_, _, comp_type) = Archive.parse_filename(tarball) 66 | for component in components: 67 | cname = DebianPkgPolicy.build_tarball_name(name, 68 | version, 69 | comp_type, 70 | os.path.dirname(tarball), 71 | component) 72 | sig = cname + '.asc' 73 | if not os.path.exists(sig): 74 | sig = None 75 | tarballs.append(DebianAdditionalTarball(cname, component, sig=sig)) 76 | if not os.path.exists(cname): 77 | raise GbpError("Cannot find component tarball %s" % cname) 78 | return tarballs 79 | 80 | 81 | def debug_exc(options): 82 | if options.verbose: 83 | traceback.print_exc() 84 | -------------------------------------------------------------------------------- /gbp/scripts/common/hook.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2016 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Common code for runniing hooks""" 18 | 19 | from gbp.command_wrappers import RunAtCommand 20 | import gbp.log 21 | 22 | 23 | class Hook(RunAtCommand): 24 | "A hook run by one of the scripts" 25 | def __init__(self, name, cmd, extra_env): 26 | RunAtCommand.__init__(self, cmd, shell=True, extra_env=extra_env) 27 | self.name = name 28 | self.run_error = '%s-hook %s' % (name, self.run_error) 29 | 30 | def __call__(self, *args, **kwargs): 31 | gbp.log.info("Running %s hook" % self.name) 32 | return RunAtCommand.__call__(self, *args, **kwargs) 33 | 34 | @staticmethod 35 | def md(a, b): 36 | "Merge two dictionaries a and b into a new one" 37 | c = a.copy() 38 | c.update(b) 39 | return c 40 | -------------------------------------------------------------------------------- /gbp/tmpfile.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012, 2015 Intel Corporation 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | # 18 | """Temporary directory handling""" 19 | 20 | import os 21 | import shutil 22 | import tempfile 23 | 24 | from gbp.errors import GbpError 25 | 26 | 27 | _old_tempdirs = [] 28 | 29 | 30 | def init_tmpdir(path, prefix): 31 | """Initialize a temporary directory structure""" 32 | try: 33 | if not os.path.exists(path): 34 | os.makedirs(path) 35 | except OSError as err: 36 | raise GbpError("Unable to create tmpdir %s (%s)" % (path, err)) 37 | 38 | tmpdir = tempfile.mkdtemp(dir=path, prefix=prefix) 39 | 40 | # Set newly created dir as the default value for all further tempfile 41 | # calls 42 | _old_tempdirs.append(tempfile.tempdir) 43 | tempfile.tempdir = tmpdir 44 | return tmpdir 45 | 46 | 47 | def del_tmpdir(): 48 | """Remove tempdir and restore tempfile module""" 49 | if _old_tempdirs: 50 | if os.path.exists(tempfile.tempdir) and \ 51 | not os.getenv('GBP_TMPFILE_NOCLEAN'): 52 | shutil.rmtree(tempfile.tempdir) 53 | tempfile.tempdir = _old_tempdirs.pop() 54 | 55 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 56 | -------------------------------------------------------------------------------- /gbp/tristate.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2011 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | 18 | """ 19 | A switch with three states: on|off|auto 20 | """ 21 | 22 | 23 | class Tristate(object): 24 | """Tri-state value: on, off or auto """ 25 | ON = True # state is on == do it 26 | OFF = False # state is off == don't do it 27 | AUTO = -1 # autodetect == do if possible 28 | 29 | # We accept true as alias for on and false as alias for off 30 | _VALID_NAMES = ['on', 'off', 'true', 'false', 'auto'] 31 | 32 | def __init__(self, val): 33 | if type(val) in [type(t) for t in (True, 1)]: 34 | if val > 0: 35 | self._state = self.ON 36 | elif val < 0: 37 | self._state = self.AUTO 38 | else: 39 | self._state = self.OFF 40 | elif isinstance(val, str): 41 | if val.lower() in ['on', 'true']: 42 | self._state = self.ON 43 | elif val.lower() in ['auto']: 44 | self._state = self.AUTO 45 | else: 46 | self._state = self.OFF 47 | elif type(val) is Tristate: 48 | self._state = val.state 49 | else: 50 | raise TypeError 51 | 52 | def __repr__(self): 53 | """ 54 | >>> Tristate('on').__repr__() 55 | 'on' 56 | >>> Tristate(True).__repr__() 57 | 'on' 58 | >>> Tristate(False).__repr__() 59 | 'off' 60 | >>> Tristate('auto').__repr__() 61 | 'auto' 62 | """ 63 | if self._state == self.ON: 64 | return 'on' 65 | elif self._state == self.AUTO: 66 | return 'auto' 67 | else: 68 | return 'off' 69 | 70 | def __nonzero__(self): 71 | """ 72 | >>> Tristate('on').__nonzero__() 73 | True 74 | >>> Tristate('auto').__nonzero__() 75 | True 76 | >>> Tristate('off').__nonzero__() 77 | False 78 | """ 79 | return self._state is not self.OFF 80 | 81 | @property 82 | def state(self): 83 | """Get current state""" 84 | return self._state 85 | 86 | def is_auto(self): 87 | return [False, True][self._state == self.AUTO] 88 | 89 | def is_on(self): 90 | return [False, True][self._state == self.ON] 91 | 92 | def is_off(self): 93 | return [False, True][self._state == self.OFF] 94 | 95 | def do(self, function, *args, **kwargs): 96 | """ 97 | Run function if tristate is on or auto, only report a failure if 98 | tristate is on since failing is o.k. for autodetect. 99 | """ 100 | if self.is_off(): 101 | return True 102 | 103 | success = function(*args, **kwargs) 104 | if not success: 105 | return [True, False][self.is_on()] 106 | 107 | return True 108 | -------------------------------------------------------------------------------- /packaging/0001-Fix-path-to-docbook-dtd-file.patch: -------------------------------------------------------------------------------- 1 | From 8725e1900b3924d3161a9a0233787334d03ca9a6 Mon Sep 17 00:00:00 2001 2 | From: "Quanah Gibson-Mount" 3 | Date: Thu, 29 Apr 2021 15:54:08 -0400 4 | Subject: [PATCH] Fix path to docbook dtd file 5 | 6 | --- 7 | docs/man.gbp.xml | 2 +- 8 | 1 file changed, 1 insertion(+), 1 deletion(-) 9 | 10 | diff --git a/docs/man.gbp.xml b/docs/man.gbp.xml 11 | index d74e906e..3a543376 100644 12 | --- a/docs/man.gbp.xml 13 | +++ b/docs/man.gbp.xml 14 | @@ -1,6 +1,6 @@ 15 | 16 | 20 | %COMMON; 21 | 22 | -- 23 | 2.27.0 24 | 25 | -------------------------------------------------------------------------------- /pydoctor.ini: -------------------------------------------------------------------------------- 1 | [pydoctor] 2 | project-name = git-buildpackage 3 | project-url = https://honk.sigxcpu.org/piki/projects/git-buildpackage/ 4 | html-output = build/apidocs 5 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 100 3 | 4 | [tool.ruff] 5 | line-length = 100 6 | # Ignore line length for now 7 | ignore = ["E501"] 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | notify2 2 | python-dateutil 3 | pyyaml 4 | requests 5 | rpm 6 | setuptools 7 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [tool:pytest] 2 | addopts = --ignore=examples/ --ignore=tests/component/rpm/data --ignore=tests/component/deb/data --doctest-modules --cov-report term --cov-report xml:coverage.xml --cov=gbp 3 | 4 | [flake8] 5 | # E501: ignore line length 6 | # E265: block comment should start with '# ' 7 | ignore=E501,E265,W504 8 | builtins=unicode,execfile,raw_input 9 | exclude = venv 10 | 11 | [metadata] 12 | name = gbp 13 | author = Guido Günther 14 | author_email = agx@sigxcpu.org 15 | url = https://honk.sigxcpu.org/piki/projects/git-buildpackage/ 16 | description = Suite to help with Debian packages in Git repositories 17 | long_description = file: README.md 18 | license = GPLv2-or-later 19 | classifiers = 20 | Environment :: Console 21 | Programming Language :: Python :: 3 22 | Topic :: Software Development :: Version Control 23 | Operating System :: POSIX :: Linux 24 | 25 | [options] 26 | include_package_data = True 27 | packages = find: 28 | python_requires = >=3.11 29 | install_requires = 30 | python-dateutil 31 | importlib-metadata; python_version<"3.8" 32 | scripts = 33 | bin/git-pbuilder 34 | bin/gbp-builder-mock 35 | 36 | [options.data_files] 37 | share/git_buildpackage = gbp.conf 38 | 39 | [options.entry_points] 40 | console_scripts = 41 | gbp = gbp.scripts.supercommand:supercommand 42 | 43 | [options.packages.find] 44 | exclude = 45 | tests 46 | tests.* 47 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # vim: set fileencoding=utf-8 : 3 | # Copyright (C) 2006-2024 Guido Günther 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | # END OF COPYRIGHT # 19 | 20 | import os 21 | import re 22 | from setuptools import setup 23 | 24 | VERSION_PY_PATH = 'gbp/version.py' 25 | 26 | 27 | def _parse_changelog(): 28 | """Get version from debian changelog and write it to gbp/version.py""" 29 | with open("debian/changelog", encoding="utf-8") as f: 30 | line = f.readline() 31 | 32 | # Parse version from changelog without external tooling so it can work 33 | # on non Debian systems. 34 | m = re.match(".* \\(([0-9a-zA-Z.~\\-:+]+)\\) ", line) 35 | if m: 36 | return m.group(1) 37 | 38 | raise ValueError('Could not parse version from debian/changelog') 39 | 40 | 41 | def _save_version_py(version): 42 | with open(VERSION_PY_PATH, 'w') as f: 43 | f.write('"The current gbp version number"\n') 44 | f.write('gbp_version = "%s"\n' % version) 45 | 46 | 47 | def _load_version(): 48 | with open(VERSION_PY_PATH, 'r') as f: 49 | version_py = f.read() 50 | version_py_globals = {} 51 | exec(version_py, version_py_globals) 52 | return version_py_globals['gbp_version'] 53 | 54 | 55 | def parse_and_fetch_version(): 56 | if os.path.exists('debian/changelog'): 57 | version = _parse_changelog() 58 | _save_version_py(version) 59 | # we could return with the version here, but instead we check that 60 | # the file has been properly written and it can be loaded back 61 | 62 | version = _load_version() 63 | return version 64 | 65 | 66 | def setup_requires(): 67 | if os.getenv('WITHOUT_PYTESTS'): 68 | return [] 69 | else: 70 | return ['pytest', 'pytest-cov'] 71 | 72 | 73 | setup(name="gbp", 74 | version=parse_and_fetch_version(), 75 | setup_requires=setup_requires(), 76 | ) 77 | -------------------------------------------------------------------------------- /tests/01_test_help.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Check if --help works""" 4 | 5 | from . import context # noqa: F401 6 | 7 | from .testutils.data import TestCaseWithData 8 | 9 | 10 | class TestHelp(TestCaseWithData): 11 | """Test help output of gbp commands""" 12 | 13 | deb_cmds = ['buildpackage', 14 | 'config', 15 | 'create_remote_repo', 16 | 'dch', 17 | 'import_orig', 18 | 'import_ref', 19 | 'import_dsc', 20 | 'pristine_tar', 21 | 'pull', 22 | 'push', 23 | 'pq', 24 | 'tag'] 25 | 26 | rpm_cmds = ['buildpackage_rpm', 27 | 'import_srpm', 28 | 'rpm_ch', 29 | 'pq_rpm'] 30 | 31 | @TestCaseWithData.feed(deb_cmds + rpm_cmds) 32 | def testHelp(self, script): 33 | module = 'gbp.scripts.%s' % script 34 | m = __import__(module, globals(), locals(), ['main'], 0) 35 | with self.assertRaises(SystemExit): 36 | m.main(['doesnotmatter', '--help']) 37 | 38 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 39 | -------------------------------------------------------------------------------- /tests/02_test_upstream_source_tar_unpack.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test L{UpstreamSource}'s tarball unpack""" 4 | 5 | from . import context 6 | 7 | import os 8 | import tarfile 9 | import unittest 10 | 11 | import gbp.pkg 12 | 13 | 14 | class TestUnpack(unittest.TestCase): 15 | """Make sure we unpack gzip and bzip2 archives correctly""" 16 | archive_prefix = "archive" 17 | 18 | def _unpack_dir(self, compression): 19 | return "%s-%s" % (self.archive_prefix, compression) 20 | 21 | def _check_files(self, files, comp): 22 | """Check if files exist in the unpacked dir""" 23 | for f in files: 24 | target = os.path.join(self._unpack_dir(comp), f) 25 | assert os.path.exists(target), "%s does not exist" % target 26 | 27 | def _create_archive(self, comp): 28 | filelist = ['README.md', 'setup.py'] 29 | 30 | name = "%s_0.1.tar.%s" % (self.archive_prefix, comp) 31 | t = tarfile.open(name=name, mode='w:%s' % comp) 32 | for f in filelist: 33 | t.add(os.path.join(self.top, f), 34 | os.path.join(self._unpack_dir(comp), f)) 35 | t.close() 36 | return name, filelist 37 | 38 | def setUp(self): 39 | self.dir = context.new_tmpdir(__name__) 40 | self.top = context.projectdir 41 | context.chdir(self.dir) 42 | self.archives = {} 43 | for ext in ["gz", "bz2"]: 44 | self.archives[ext] = self._create_archive(ext) 45 | 46 | def tearDown(self): 47 | context.teardown() 48 | 49 | def test_upstream_source_type(self): 50 | for (comp, archive) in self.archives.items(): 51 | source = gbp.pkg.UpstreamSource(archive[0]) 52 | assert source.is_orig() is True 53 | assert source.is_dir() is False 54 | assert source.unpacked is None 55 | source.unpack(".") 56 | assert source.is_orig() is True 57 | assert source.is_dir() is False 58 | assert isinstance(source.unpacked, str) 59 | 60 | def test_upstream_source_unpack(self): 61 | for (comp, archive) in self.archives.items(): 62 | source = gbp.pkg.UpstreamSource(archive[0]) 63 | source.unpack(".") 64 | self._check_files(archive[1], comp) 65 | 66 | def test_upstream_source_unpack_no_filter(self): 67 | for (comp, archive) in self.archives.items(): 68 | source = gbp.pkg.UpstreamSource(archive[0]) 69 | source.unpack(".", []) 70 | self._check_files(archive[1], comp) 71 | 72 | def test_upstream_source_unpack_filtered(self): 73 | exclude = "README.md" 74 | 75 | for (comp, archive) in self.archives.items(): 76 | source = gbp.pkg.UpstreamSource(archive[0]) 77 | source.unpack(".", [exclude]) 78 | archive[1].remove(exclude) 79 | self._check_files(archive[1], comp) 80 | 81 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 82 | -------------------------------------------------------------------------------- /tests/06_test_upstream_source.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test the L{UpstreamSource} class""" 4 | 5 | from . import context 6 | 7 | import glob 8 | import os 9 | import tarfile 10 | import unittest 11 | import zipfile 12 | 13 | from gbp.pkg import UpstreamSource 14 | 15 | 16 | class TestDir(unittest.TestCase): 17 | def setUp(self): 18 | self.tmpdir = context.new_tmpdir(__name__) 19 | self.upstream_dir = self.tmpdir.join('test-1.0') 20 | os.mkdir(self.upstream_dir) 21 | 22 | def test_directory(self): 23 | """Upstream source is a directory""" 24 | source = UpstreamSource(self.upstream_dir) 25 | self.assertEqual(source.is_orig(), False) 26 | self.assertEqual(source.path, self.upstream_dir) 27 | self.assertEqual(source.unpacked, self.upstream_dir) 28 | self.assertEqual(source.guess_version(), ('test', '1.0')) 29 | 30 | def tearDown(self): 31 | context.teardown() 32 | 33 | 34 | class TestTar(unittest.TestCase): 35 | """Test if packing tar archives works""" 36 | def _check_tar(self, us, positive=[], negative=[]): 37 | t = tarfile.open(name=us.path, mode="r:bz2") 38 | for f in positive: 39 | i = t.getmember(f) 40 | self.assertEqual(type(i), tarfile.TarInfo) 41 | 42 | for f in negative: 43 | try: 44 | t.getmember(f) 45 | self.fail("Found %s in archive" % f) 46 | except KeyError: 47 | pass 48 | t.close() 49 | 50 | def setUp(self): 51 | self.tmpdir = context.new_tmpdir(__name__) 52 | self.source = UpstreamSource(os.path.join(context.projectdir, "gbp")) 53 | 54 | def tearDown(self): 55 | context.teardown() 56 | 57 | def test_pack_tar(self): 58 | """Check if packing tar archives works""" 59 | target = self.tmpdir.join("gbp_0.1.tar.bz2") 60 | repacked = self.source.pack(target) 61 | self.assertEqual(repacked.is_orig(), True) 62 | self.assertEqual(repacked.is_dir(), False) 63 | self.assertEqual(repacked.guess_version(), ('gbp', '0.1')) 64 | self._check_tar(repacked, ["gbp/errors.py", "gbp/__init__.py"]) 65 | 66 | def test_pack_filtered(self): 67 | """Check if filtering out files works""" 68 | target = self.tmpdir.join("gbp_0.1.tar.bz2") 69 | repacked = self.source.pack(target, ["__init__.py"]) 70 | self.assertEqual(repacked.is_orig(), True) 71 | self.assertEqual(repacked.is_dir(), False) 72 | self._check_tar(repacked, ["gbp/errors.py"], 73 | ["gbp/__init__.py"]) 74 | 75 | 76 | class TestZip(unittest.TestCase): 77 | """Test if unpacking zip archives works""" 78 | def setUp(self): 79 | self.tmpdir = context.new_tmpdir(__name__) 80 | self.zipfile = self.tmpdir.join("gbp-0.1.zip") 81 | z = zipfile.ZipFile(self.zipfile, "w") 82 | for f in glob.glob(os.path.join(context.projectdir, "gbp/*.py")): 83 | z.write(f, f, zipfile.ZIP_DEFLATED) 84 | z.close() 85 | 86 | def tearDown(self): 87 | context.teardown() 88 | 89 | def test_unpack(self): 90 | source = UpstreamSource(self.zipfile) 91 | self.assertEqual(source.is_orig(), False) 92 | self.assertEqual(source.is_dir(), False) 93 | self.assertEqual(source.unpacked, None) 94 | self.assertEqual(source.guess_version(), ('gbp', '0.1')) 95 | source.unpack(str(self.tmpdir)) 96 | self.assertNotEqual(source.unpacked, None) 97 | -------------------------------------------------------------------------------- /tests/07_test_fastimport.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test L{FastImport} class""" 4 | 5 | from . import context 6 | 7 | import os 8 | 9 | import gbp.log 10 | import gbp.git 11 | 12 | repo = None 13 | fastimport = None 14 | tf_name = 'testfile' 15 | tl_name = 'a_testlink' 16 | 17 | 18 | def setup(): 19 | global repo 20 | 21 | tmpdir = context.new_tmpdir(__name__) 22 | repo = gbp.git.GitRepository.create(tmpdir.join('test_repo')) 23 | 24 | 25 | def teardown(): 26 | context.teardown() 27 | 28 | 29 | def test_init_fastimport(): 30 | """Create a fastimport object""" 31 | global fastimport 32 | fastimport = gbp.git.FastImport(repo) 33 | assert fastimport, "Failed to init FastImport" 34 | 35 | 36 | def test_add_file(): 37 | """Add a file via fastimport""" 38 | author = repo.get_author_info() 39 | fastimport.start_commit('master', author, "a commit") 40 | fastimport.deleteall() 41 | testfile = os.path.join(repo.path, '.git', 'description') 42 | fastimport.add_file(b'./testfile', 43 | open(testfile, 'rb'), 44 | os.path.getsize(testfile)) 45 | 46 | 47 | def test_add_symlink(): 48 | """Add a symbolic link via fastimport""" 49 | author = repo.get_author_info() 50 | fastimport.start_commit('master', author, "a 2nd commit") 51 | fastimport.add_symlink(tl_name, tf_name) 52 | 53 | 54 | def test_close(): 55 | fastimport.close() 56 | 57 | 58 | def test_result(): 59 | repo.force_head('master', hard=True) 60 | 61 | testfile = os.path.join(repo.path, tf_name) 62 | testlink = os.path.join(repo.path, tl_name) 63 | 64 | assert os.path.exists(testfile), "%s doesn't exist" % testfile 65 | assert os.path.lexists(testlink), "%s doesn't exist" % testlink 66 | assert os.readlink(testlink) == tf_name 67 | -------------------------------------------------------------------------------- /tests/08_test_patch_data/916545.patch: -------------------------------------------------------------------------------- 1 | --- 2 | --- /dev/null 3 | +++ b/foo 4 | @@ -0,0 +1,1 @@ 5 | +foo 6 | -------------------------------------------------------------------------------- /tests/08_test_patch_data/base64.patch: -------------------------------------------------------------------------------- 1 | From: Nick Leverton 2 | Date: Tue, 11 Jul 2017 22:25:43 -0300 3 | Subject: Sort files in archive (reproducible builds) 4 | MIME-Version: 1.0 5 | Content-Type: text/plain; charset="utf-8" 6 | Content-Transfer-Encoding: base64 7 | 8 | U29ydCBmaWxlcyB3aGVuIHVzaW5nIG1lcmdlbGliIHRvIGNyZWF0ZSBsaWJudWxsbWFpbGVyLmEs 9 | IHRvIGdldApyZXByb2R1Y2libGUgYnVpbGQKCkF1dGhvcjogQWxleGlzIEJpZW52ZW7DvGUgPHBh 10 | ZG9AcGFzc29pcmUuZnI+Cg== 11 | --- 12 | lib/mergelib.sh | 2 +- 13 | 1 file changed, 1 insertion(+), 1 deletion(-) 14 | 15 | diff --git a/lib/mergelib.sh b/lib/mergelib.sh 16 | index f9b7a94..4e71079 100644 17 | --- a/lib/mergelib.sh 18 | +++ b/lib/mergelib.sh 19 | @@ -12,5 +12,5 @@ for input in "$@"; do 20 | "${AR:-ar}" x ../../"$input" 21 | cd .. 22 | done 23 | -"${AR:-ar}" rc ../"$archive" */* 24 | +"${AR:-ar}" rc ../"$archive" `LC_ALL=C ls */*` 25 | "${RANLIB:-ranlib}" ../"$archive" 26 | -------------------------------------------------------------------------------- /tests/08_test_patch_data/dep3-iso8859-1.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/08_test_patch_data/dep3-iso8859-1.patch -------------------------------------------------------------------------------- /tests/08_test_patch_data/dep3-longdesc-bug.patch: -------------------------------------------------------------------------------- 1 | Author: Ben Hutchings 2 | Description: Summary 3 | Long description 4 | Bug: https://bugs.example.org/123456 5 | 6 | --- /dev/null 7 | +++ b/foo 8 | @@ -0,0 +1,1 @@ 9 | +foo 10 | -------------------------------------------------------------------------------- /tests/08_test_patch_data/patch1.diff: -------------------------------------------------------------------------------- 1 | From: foo 2 | Date: Sat, 24 Dec 2011 12:05:53 +0100 3 | Subject: This is 4 | patch1 5 | 6 | This is the long description. 7 | It can span several lines. 8 | -------------------------------------------------------------------------------- /tests/08_test_patch_data/usbip-fix-misuse-of-strncpy.patch: -------------------------------------------------------------------------------- 1 | From: Ben Hutchings 2 | Date: Fri, 20 Jul 2018 01:30:24 +0100 3 | Subject: usbip: Fix misuse of strncpy() 4 | Bug-Debian: https://bugs.debian.org/897802 5 | 6 | gcc 8 reports: 7 | 8 | usbip_device_driver.c: In function ‘read_usb_vudc_device’: 9 | usbip_device_driver.c:106:2: error: ‘strncpy’ specified bound 256 equals destination size [-Werror=stringop-truncation] 10 | strncpy(dev->path, path, SYSFS_PATH_MAX); 11 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | usbip_device_driver.c:125:2: error: ‘strncpy’ specified bound 32 equals destination size [-Werror=stringop-truncation] 13 | strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE); 14 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | 16 | I'm not convinced it makes sense to truncate the copied strings here, 17 | but since we're already doing so let's ensure they're still null- 18 | terminated. We can't easily use strlcpy() here, so use snprintf(). 19 | 20 | usbip_common.c has the same problem. 21 | 22 | Signed-off-by: Ben Hutchings 23 | --- 24 | --- a/tools/usb/usbip/libsrc/usbip_common.c 25 | +++ b/tools/usb/usbip/libsrc/usbip_common.c 26 | @@ -226,8 +226,8 @@ int read_usb_device(struct udev_device * 27 | path = udev_device_get_syspath(sdev); 28 | name = udev_device_get_sysname(sdev); 29 | 30 | - strncpy(udev->path, path, SYSFS_PATH_MAX); 31 | - strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE); 32 | + snprintf(udev->path, SYSFS_PATH_MAX, "%s", path); 33 | + snprintf(udev->busid, SYSFS_BUS_ID_SIZE, "%s", name); 34 | 35 | sscanf(name, "%u-%u", &busnum, &devnum); 36 | udev->busnum = busnum; 37 | --- a/tools/usb/usbip/libsrc/usbip_device_driver.c 38 | +++ b/tools/usb/usbip/libsrc/usbip_device_driver.c 39 | @@ -103,7 +103,7 @@ int read_usb_vudc_device(struct udev_dev 40 | copy_descr_attr16(dev, &descr, idProduct); 41 | copy_descr_attr16(dev, &descr, bcdDevice); 42 | 43 | - strncpy(dev->path, path, SYSFS_PATH_MAX); 44 | + snprintf(dev->path, SYSFS_PATH_MAX, "%s", path); 45 | 46 | dev->speed = USB_SPEED_UNKNOWN; 47 | speed = udev_device_get_sysattr_value(sdev, "current_speed"); 48 | @@ -122,7 +122,7 @@ int read_usb_vudc_device(struct udev_dev 49 | dev->busnum = 0; 50 | 51 | name = udev_device_get_sysname(plat); 52 | - strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE); 53 | + snprintf(dev->busid, SYSFS_BUS_ID_SIZE, "%s", name); 54 | return 0; 55 | err: 56 | fclose(fd); 57 | -------------------------------------------------------------------------------- /tests/09_test_git_repository.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """ 4 | Test L{GitRepository} 5 | 6 | Test things here that don't fit nicely into the doctests that 7 | also make up the API documentation. 8 | """ 9 | 10 | from . import context # noqa: F401 11 | from . import testutils 12 | 13 | import os 14 | 15 | import gbp.log 16 | import gbp.git 17 | import gbp.errors 18 | 19 | 20 | class TestWriteTree(testutils.DebianGitTestRepo): 21 | def _write_testtree(self): 22 | """Write a test tree""" 23 | paths = [] 24 | for i in range(4): 25 | path = os.path.join(self.repo.path, 'testfile%d' % i) 26 | with open(path, 'w') as f: 27 | print("testdata %d" % i, file=f) 28 | paths.append(path) 29 | return paths 30 | 31 | def test_write_tree_index_nonexistent(self): 32 | """Write out index file to non-existent dir""" 33 | paths = self._write_testtree() 34 | self.repo.add_files(paths) 35 | with self.assertRaises(gbp.git.GitRepositoryError): 36 | self.repo.write_tree('/does/not/exist') 37 | 38 | def test_write_tree(self): 39 | """Write out index file to alternate index file""" 40 | index = os.path.join(self.repo.git_dir, 'gbp_index') 41 | expected_sha1 = '4b825dc642cb6eb9a060e54bf8d69288fbee4904' 42 | 43 | paths = self._write_testtree() 44 | self.repo.add_files(paths) 45 | sha1 = self.repo.write_tree(index) 46 | self.assertTrue(os.path.exists(index)) 47 | self.assertEqual(sha1, expected_sha1) 48 | self.assertTrue(self.repo.has_treeish(expected_sha1)) 49 | 50 | def test_commit_tree(self): 51 | """Commit a tree""" 52 | expected_sha1 = 'ea63fcee40675a5f82ea6bedbf29ca86d89c5f63' 53 | paths = self._write_testtree() 54 | self.repo.add_files(paths) 55 | sha1 = self.repo.write_tree() 56 | self.assertEqual(sha1, expected_sha1) 57 | self.assertTrue(self.repo.has_treeish(expected_sha1)) 58 | commit = self.repo.commit_tree(sha1, "first commit", parents=[], 59 | committer=dict(name='foo', 60 | email='foo@example.com'), 61 | author=dict(name='bar', 62 | email='bar@example.com'), 63 | ) 64 | self.assertEqual(len(commit), 40) 65 | # commit the same tree again using the previous commit as parent 66 | self.repo.commit_tree(sha1, "second commit", parents=[commit]) 67 | # commit the same tree again using a non-existent parent 68 | with self.assertRaises(gbp.errors.GbpError): 69 | self.repo.commit_tree(sha1, "failed commit", ['doesnotexist']) 70 | 71 | 72 | class TestHasBranch(testutils.DebianGitTestRepo): 73 | def test_has_branch(self): 74 | self.add_file('whatever') 75 | self.repo.create_branch("foo") 76 | self.assertTrue(self.repo.has_branch("foo")) 77 | # Don't be too sloppy on (#813298) 78 | self.repo.create_branch("refs/heads/bar") 79 | self.assertFalse(self.repo.has_branch("bar")) 80 | 81 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 82 | -------------------------------------------------------------------------------- /tests/10_test_get_upstream_tree.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test L{export_orig}'s git_archive_get_upstream_tree method""" 4 | 5 | from . import context # noqa: F401 6 | from . import testutils 7 | 8 | import gbp.errors 9 | import gbp.scripts.export_orig as export_orig 10 | 11 | 12 | class MockOptions(object): 13 | def __init__(self, 14 | upstream_branch=None, 15 | upstream_tree=None, 16 | upstream_tag=None): 17 | self.upstream_branch = upstream_branch 18 | self.upstream_tree = upstream_tree 19 | self.upstream_tag = upstream_tag 20 | 21 | 22 | class TestGetUpstreamTree(testutils.DebianGitTestRepo): 23 | class source: 24 | upstream_version = '1.0~rc3' 25 | 26 | def test_valid_upstream_branch(self): 27 | """Get upstream tree from a valid upstream branch""" 28 | self.add_file('foo') 29 | self.repo.create_branch('upstream') 30 | options = MockOptions(upstream_tree='BRANCH', 31 | upstream_branch='upstream') 32 | t = export_orig.git_archive_get_upstream_tree(self.repo, None, options) 33 | self.assertEqual(t, 'upstream') 34 | 35 | def test_invalid_upstream_branch(self): 36 | """Getting upstream tree from a invalid upstream branch must fail""" 37 | self.add_file('foo') 38 | options = MockOptions(upstream_tree='BRANCH', 39 | upstream_branch='upstream') 40 | with self.assertRaises(gbp.errors.GbpError): 41 | export_orig.git_archive_get_upstream_tree(self.repo, None, options) 42 | 43 | def test_valid_tree(self): 44 | """Get upstream tree from a valid upstream tree""" 45 | self.add_file('foo') 46 | tree = self.repo.rev_parse('master') 47 | options = MockOptions(upstream_tree=tree) 48 | t = export_orig.git_archive_get_upstream_tree(self.repo, None, options) 49 | self.assertEqual(t, tree) 50 | 51 | def test_invalid_tree(self): 52 | """Getting upstream tree from an invalid tree must fail""" 53 | self.add_file('foo') 54 | options = MockOptions(upstream_tree='doesnotexist') 55 | with self.assertRaises(gbp.errors.GbpError): 56 | export_orig.git_archive_get_upstream_tree(self.repo, None, options) 57 | 58 | def test_valid_tag(self): 59 | """Get upstream tree from a valid tag""" 60 | self.add_file('foo') 61 | self.repo.rev_parse('master') 62 | self.repo.create_tag('upstream/1.0_rc3') 63 | options = MockOptions(upstream_tree="TAG", 64 | upstream_tag="upstream/%(version)s") 65 | tag = export_orig.git_archive_get_upstream_tree(self.repo, self.source, options) 66 | self.assertEqual(tag, "upstream/1.0_rc3") 67 | 68 | def test_invalid_tag(self): 69 | """Getting upstream tree from an invalid tag must fail""" 70 | self.add_file('foo') 71 | options = MockOptions(upstream_tree="TAG", 72 | upstream_tag="upstream/%(version)s") 73 | with self.assertRaises(gbp.errors.GbpError): 74 | export_orig.git_archive_get_upstream_tree(self.repo, self.source, options) 75 | 76 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 77 | -------------------------------------------------------------------------------- /tests/14_test_gbp_import_dscs.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # (C) 2012 Guido Günther 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, please see 15 | # 16 | """Test L{gbp.pq}""" 17 | 18 | from . import context 19 | from . import testutils 20 | 21 | import gbp.log 22 | import gbp.scripts.import_dscs as import_dscs 23 | 24 | from gbp.errors import GbpError 25 | 26 | 27 | class StubGitImportDsc(object): 28 | """ 29 | A Stub for GitImportDsc. 30 | """ 31 | def __init__(self, args): 32 | self.failfile = None 33 | for arg in args: 34 | if arg.startswith('--failfile'): 35 | self.failfile = "%s.dsc" % arg.split('=')[1] 36 | 37 | def importdsc(self, dsc): 38 | """ 39 | Stub the dsc import and fail if we were told to do 40 | so by the --failfile option. 41 | """ 42 | return 1 if dsc.filename == self.failfile else 0 43 | 44 | 45 | class DscStub(object): 46 | def __init__(self, filename, version): 47 | self.filename = filename 48 | self.version = version 49 | self.dscfile = filename 50 | 51 | @classmethod 52 | def parse(cls, filename): 53 | # filename is like file1.dsc, file2.dsc, use 54 | # the digit as version number 55 | version = filename[4] 56 | return cls(filename, version) 57 | 58 | 59 | class TestImportDscs(testutils.DebianGitTestRepo): 60 | """Test L{gbp.scripts.import_dscs}'s """ 61 | 62 | def setUp(self): 63 | testutils.DebianGitTestRepo.setUp(self) 64 | context.chdir(self.repo.path) 65 | self.orig_err = gbp.log.err 66 | gbp.log.err = self._check_err_msg 67 | 68 | self.safed_GitImportDsc = import_dscs.GitImportDsc 69 | self.safed_DscFile = import_dscs.DscFile 70 | import_dscs.GitImportDsc = StubGitImportDsc 71 | import_dscs.DscFile = DscStub 72 | 73 | def _check_err_msg(self, err): 74 | self.assertIsInstance(err, GbpError) 75 | self.assertIn("Failed to import", str(err)) 76 | 77 | def test_import_success(self): 78 | """Test importing success with stub""" 79 | ret = import_dscs.main(['argv0', 'file1.dsc', 'file2.dsc']) 80 | self.assertEqual(ret, 0) 81 | 82 | def test_import_fail_first(self): 83 | ret = import_dscs.main(['argv0', 84 | '--failfile=file1', 85 | 'file1.dsc']) 86 | self.assertEqual(ret, 1) 87 | 88 | def test_import_fail_second(self): 89 | ret = import_dscs.main(['argv0', 90 | '--failfile=file1', 91 | '--failfile=file2', 92 | 'file1.dsc', 93 | 'file2.dsc']) 94 | self.assertEqual(ret, 1) 95 | 96 | def tearDown(self): 97 | gbp.log.err = self.orig_err 98 | testutils.DebianGitTestRepo.tearDown(self) 99 | context.teardown() 100 | 101 | import_dscs.GitImportDsc = self.safed_GitImportDsc 102 | import_dscs.DscFile = self.safed_DscFile 103 | -------------------------------------------------------------------------------- /tests/16_test_supercommand.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # (C) 2013 Guido Günther 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, please see 15 | # 16 | """Test L{gbp} command wrapper""" 17 | 18 | import unittest 19 | import gbp.scripts.supercommand 20 | 21 | from tests.testutils import capture_stdout, capture_stderr 22 | 23 | 24 | class TestSuperCommand(unittest.TestCase): 25 | 26 | def test_import(self): 27 | """Test the importer itself""" 28 | with self.assertRaises(ImportError): 29 | gbp.scripts.supercommand.import_command('not.allowed') 30 | with self.assertRaises(ImportError): 31 | gbp.scripts.supercommand.import_command('not/allowed') 32 | with self.assertRaises(ImportError): 33 | gbp.scripts.supercommand.import_command('0notallowed') 34 | self.assertIsNotNone(gbp.scripts.supercommand.import_command('pq')) 35 | 36 | def test_invalid_command(self): 37 | """Test if we fail correctly with an invalid command""" 38 | with capture_stderr(): 39 | self.assertEqual(gbp.scripts.supercommand.supercommand( 40 | ['argv0', 'asdf']), 2) 41 | self.assertEqual(gbp.scripts.supercommand.supercommand( 42 | ['argv0', 'asdf', '--verbose']), 2) 43 | 44 | def test_list_commands(self): 45 | """Invoking with --list-cmds must not raise an error""" 46 | with capture_stdout() as out: 47 | self.assertEqual(gbp.scripts.supercommand.supercommand(['argv0', 48 | '--list-cmds']), 0) 49 | for cmd in ['import-orig', 'create-remote-repo', 'pq']: 50 | self.assertIn("%s - " % cmd, out.output()) 51 | 52 | def test_help_command(self): 53 | """Invoking with --help must not raise an error""" 54 | self.assertEqual(gbp.scripts.supercommand.supercommand( 55 | ['argv0', '--help']), 0) 56 | 57 | def test_missing_arg(self): 58 | self.assertEqual(gbp.scripts.supercommand.supercommand( 59 | ['argv0']), 1) 60 | -------------------------------------------------------------------------------- /tests/17_test_dch_guess_documented_commit.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test L{Changelog}'s guess_version_from_upstream""" 4 | 5 | from . import context # noqa: F401 6 | from . import testutils 7 | 8 | from gbp.scripts import dch 9 | 10 | 11 | class TestGuessDocumentedCommit(testutils.DebianGitTestRepo): 12 | def setUp(self): 13 | self.version = '1.0-1' 14 | self.tagformat = 'debian/%(version)s' 15 | 16 | testutils.DebianGitTestRepo.setUp(self) 17 | 18 | def test_01_from_snapshot_banner(self): 19 | """ 20 | Guess the commit to start from from the snapshot banner 21 | """ 22 | cp = testutils.MockedChangeLog(self.version, 23 | "*** SNAPSHOT build @12345 ***") 24 | guessed_commit = dch.guess_documented_commit(cp, None, None) 25 | self.assertEqual(guessed_commit, '12345') 26 | 27 | def test_02_from_tag(self): 28 | """ 29 | Guess the commit to start from from the tag matching 30 | the topmost version in the changelog 31 | """ 32 | cp = testutils.MockedChangeLog(self.version) 33 | 34 | self.add_file('doesnot', 'matter') 35 | tag = self.repo.version_to_tag(self.tagformat, 36 | self.version) 37 | self.repo.create_tag(name=tag, 38 | msg="Debian release %s" % self.version, 39 | sign=False) 40 | commit = self.repo.rev_parse('%s^0' % tag) 41 | guessed_commit = dch.guess_documented_commit(cp, 42 | self.repo, 43 | self.tagformat) 44 | self.assertEqual(guessed_commit, commit) 45 | 46 | def test_03_from_changelog_commit(self): 47 | """ 48 | Guess the commit to start from from the commit that 49 | last touched the changelog 50 | """ 51 | cp = testutils.MockedChangeLog(self.version) 52 | 53 | self.add_file('debian/changelog', 'foo') 54 | commit = self.repo.head 55 | self.add_file('doesnot', 'matter') 56 | guessed_commit = dch.guess_documented_commit(cp, 57 | self.repo, 58 | self.tagformat) 59 | self.assertEqual(guessed_commit, commit) 60 | 61 | def test_04_not_touched(self): 62 | """ 63 | None of the above matched so we want to start from 64 | the beginning of history 65 | """ 66 | cp = testutils.MockedChangeLog(self.version) 67 | 68 | self.add_file('doesnot', 'matter') 69 | self.add_file('doesnot', 'mattereither') 70 | guessed_commit = dch.guess_documented_commit(cp, 71 | self.repo, 72 | self.tagformat) 73 | self.assertIsNone(guessed_commit) 74 | -------------------------------------------------------------------------------- /tests/23_test_dch_extract_bts_cmds.py: -------------------------------------------------------------------------------- 1 | # (C) 2015 Jonathan Toppins 2 | # This program is free software; you can redistribute it and/or modify 3 | # it under the terms of the GNU General Public License as published by 4 | # the Free Software Foundation; either version 2 of the License, or 5 | # (at your option) any later version. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | # GNU General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU General Public License 13 | # along with this program; if not, please see 14 | # 15 | """Test gbp.dch.extract_bts_cmds()""" 16 | 17 | import unittest 18 | 19 | from gbp.dch import extract_bts_cmds 20 | 21 | 22 | class OptionsStub: 23 | def __init__(self): 24 | self.meta_closes = "Closes|LP" 25 | self.meta_closes_bugnum = r'(?:bug|issue)?\#?\s?\d+' 26 | 27 | 28 | class TestExtractBTSCmds(unittest.TestCase): 29 | def test_debian_commands(self): 30 | """Test default BTS command extraction that is applicable to Debian""" 31 | options = OptionsStub() 32 | lines = """This is a test commit 33 | 34 | Closes: bug#12345 35 | Closes: 456 36 | """ 37 | bugs, dummy = extract_bts_cmds(lines.split('\n'), options) 38 | self.assertEqual(bugs, {'Closes': ['bug#12345', '456']}) 39 | 40 | def test_nondebian_commands(self): 41 | """Test non-default BTS commands. We use the example given in the 42 | documentation manpages.""" 43 | options = OptionsStub() 44 | options.meta_closes_bugnum = r'(?:bug)?\s*ex-\d+' 45 | lines = """This is a test commit 46 | some more lines... 47 | 48 | Closes: bug EX-12345 49 | Closes: ex-01273 50 | Closes: bug ex-1ab 51 | Closes: EX--12345 52 | """ 53 | bugs, dummy = extract_bts_cmds(lines.split('\n'), options) 54 | self.assertEqual(bugs, {'Closes': ['bug EX-12345', 'ex-01273', 55 | 'bug ex-1']}) 56 | -------------------------------------------------------------------------------- /tests/25_test_broken_gbp_conf.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Check if we fail correcdtly on broken gbp.conf""" 4 | 5 | from . import context 6 | 7 | from . testutils.data import TestCaseWithData 8 | from . testutils.gbplogtester import GbpLogTester 9 | 10 | import os 11 | import unittest 12 | 13 | 14 | class TestBrokenConfig(TestCaseWithData, GbpLogTester): 15 | """Test that broken config gives a sensible error for all commands""" 16 | 17 | cmds = ['buildpackage', 18 | 'clone', 19 | 'config', 20 | 'create_remote_repo', 21 | 'dch', 22 | 'import_orig', 23 | 'import_dsc', 24 | 'pull', 25 | 'pq', 26 | 'import_srpm', 27 | 'buildpackage_rpm', 28 | 'pq_rpm', 29 | 'rpm_ch'] 30 | 31 | def __init__(self, methodName='runTest'): 32 | unittest.TestCase.__init__(self, methodName) 33 | GbpLogTester.__init__(self) 34 | 35 | def setUp(self): 36 | tmpdir = str(context.new_tmpdir('bar')) 37 | confname = os.path.join(tmpdir, 'gbp.conf') 38 | with open(confname, 'w') as f: 39 | f.write("this is a broken config\n") 40 | os.environ['GBP_CONF_FILES'] = confname 41 | self._capture_log(True) 42 | 43 | def tearDown(self): 44 | del os.environ['GBP_CONF_FILES'] 45 | 46 | @TestCaseWithData.feed(cmds) 47 | def testBrokenConf(self, cmd): 48 | module = 'gbp.scripts.%s' % cmd 49 | try: 50 | m = __import__(module, globals(), locals(), ['main'], 0) 51 | ret = m.main([cmd, '--help']) 52 | self.assertEqual(ret, 3) 53 | except Exception as e: 54 | self.assertTrue(False, "Caught '%s'" % e) 55 | self._check_log(-1, "See 'man gbp.conf' for the format.") 56 | self._clear_log() 57 | 58 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 59 | -------------------------------------------------------------------------------- /tests/26_test_dch_extract_thanks.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2015 Jonathan Toppins 4 | # (C) 2016 Guido Günther 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | """Test gbp.dch.extract_thanks_info()""" 19 | 20 | import unittest 21 | 22 | from gbp.dch import extract_thanks_info 23 | 24 | 25 | class OptionsStub: 26 | def __init__(self): 27 | self.meta_closes = "Closes|LP" 28 | self.meta_closes_bugnum = r'(?:bug|issue)?\#?\s?\d+' 29 | 30 | 31 | class TestExtractThanks(unittest.TestCase): 32 | def test_debian_commands(self): 33 | """Test default thanks extraction""" 34 | lines = """ 35 | thAnks: a lot 36 | Thanks: everyone""" 37 | 38 | lines += " \n" # Add some trailing whitespace 39 | bugs, dummy = extract_thanks_info(lines.split('\n'), None) 40 | self.assertEqual(bugs, ['a lot', 'everyone']) 41 | -------------------------------------------------------------------------------- /tests/27_test_create_remote_repo.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # (C) 2016 Guido Günther 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, please see 15 | # 16 | """Test the L{gbp} create_remote_repo command""" 17 | 18 | import os 19 | import unittest 20 | import gbp.scripts.create_remote_repo as create_remote_repo 21 | 22 | 23 | class TestGbpCreateRemoteRepoCommand(unittest.TestCase): 24 | def setUp(self): 25 | self.conffiles_save = os.environ.get('GBP_CONF_FILES') 26 | 27 | def tearDown(self): 28 | if self.conffiles_save: 29 | os.environ['GBP_CONF_FILES'] = self.conffiles_save 30 | 31 | def test_no_config_templates(self): 32 | self.confname = 'tests/data/gbp_nonexistent.conf' 33 | self.assertFalse(os.path.exists(self.confname)) 34 | os.environ['GBP_CONF_FILES'] = self.confname 35 | 36 | _, _, sections = create_remote_repo.parse_args(['create-remote-repo']) 37 | self.assertEqual(create_remote_repo.get_config_names(sections), 38 | []) 39 | 40 | def test_list_config_templates(self): 41 | self.confname = 'tests/data/gbp_create_remote_repo.conf' 42 | self.assertTrue(os.path.exists(self.confname)) 43 | os.environ['GBP_CONF_FILES'] = self.confname 44 | 45 | _, _, sections = create_remote_repo.parse_args(['create-remote-repo']) 46 | self.assertEqual(create_remote_repo.get_config_names(sections), 47 | ['config1', 'config2']) 48 | -------------------------------------------------------------------------------- /tests/28_test_gbp_git_repository_commit_dir.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | import os 4 | 5 | from . testutils import DebianGitTestRepo 6 | from gbp.git.repository import GitRepositoryError 7 | 8 | 9 | class TestGitRepositoryCommitDir(DebianGitTestRepo): 10 | def setUp(self): 11 | DebianGitTestRepo.setUp(self) 12 | self.content = os.path.join(str(self.tmpdir), 'new') 13 | os.mkdir(self.content) 14 | with open(os.path.join(self.content, 'file1'), 'w') as f: 15 | f.write('content1') 16 | 17 | def test_simple(self): 18 | self.repo.commit_dir(self.content, 19 | 'new content', 20 | 'master', 21 | create_missing_branch=True) 22 | self.assertEqual(self.repo.show('master:file1'), b'content1') 23 | 24 | def test_long_reflog(self): 25 | """Make sure we fail on onverly long msg resulting in an 26 | overly long reflog enry""" 27 | with self.assertRaises(GitRepositoryError): 28 | self.repo.commit_dir(self.content, 29 | 'foo' * 100000, 30 | 'master', 31 | create_missing_branch=True) 32 | 33 | def test_long_msg_854333(self): 34 | """Make sure we shorten the reflog entry properly""" 35 | self.repo.commit_dir(self.content, 36 | 'foo\n' * 100000, 37 | 'master', 38 | create_missing_branch=True) 39 | self.assertEqual(self.repo.show('master:file1'), b'content1') 40 | out, dummy, ret = self.repo._git_inout('reflog', []) 41 | self.assertEqual(ret, 0) 42 | self.assertIn(b'HEAD@{0}: gbp: foo\n', out) 43 | -------------------------------------------------------------------------------- /tests/29_test_gbp_clone.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | from gbp.scripts.clone import vcs_git_url 3 | 4 | import unittest 5 | from unittest.mock import patch 6 | 7 | from . testutils import skip_without_cmd 8 | 9 | 10 | class TestGbpClone(unittest.TestCase): 11 | show_src = """ 12 | Version: 0.6.22 13 | Standards-Version: 3.9.4 14 | Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git 15 | 16 | Version: 0.8.14 17 | Standards-Version: 3.9.8 18 | Vcs-Git: https://git.sigxcpu.org/cgit/git-buildpackage/ -b foo 19 | 20 | Version: 0.8.12.2 21 | Standards-Version: 3.9.8 22 | Vcs-Git: https://git.sigxcpu.org/cgit/git-buildpackage/ 23 | 24 | Version: 0.6.0~git20120601 25 | Standards-Version: 3.9.3 26 | Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git 27 | 28 | """ 29 | 30 | @skip_without_cmd('dpkg') 31 | @patch('gbp.scripts.clone.apt_showsrc', return_value=show_src) 32 | def test_vcs_git_url(self, patch): 33 | self.assertEqual(vcs_git_url('git-buildpackage'), 34 | 'https://git.sigxcpu.org/cgit/git-buildpackage/') 35 | -------------------------------------------------------------------------------- /tests/30_test_deb_changelog.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """ 4 | Test L{gbp.deb.changelog.Changelog} 5 | 6 | Test things here that don't fit nicely into the doctests that 7 | also make up the API documentation. 8 | """ 9 | 10 | from . import context # noqa: F401 11 | from . testutils import skip_without_cmd 12 | import os 13 | import unittest 14 | 15 | from gbp.deb.changelog import ChangeLog 16 | from gbp.command_wrappers import CommandExecFailed 17 | 18 | 19 | class TestQuoting(unittest.TestCase): 20 | def test_comma(self): 21 | """Test we properly parse maintainers with comma #737623""" 22 | changes = """git-buildpackage (0.9.2) unstable; urgency=low 23 | 24 | * List of changes 25 | 26 | -- Guido Günther, aftercomma Sun, 12 Nov 2017 19:00:00 +0200 27 | """ 28 | cl = ChangeLog(changes) 29 | self.assertEqual(cl.author, 'Guido Günther, aftercomma') 30 | self.assertEqual(cl.email, 'agx@sigxcpu.org') 31 | 32 | 33 | class TestEncoding(unittest.TestCase): 34 | def test_nul(self): 35 | """Test we remove NUL characters from strings when parsing (#981340)""" 36 | changes = """git-buildpackage (0.9.2) unstable; urgency=low 37 | 38 | * List of ch\0nges 39 | 40 | -- User N\0me Sun, 12 Nov 2017 19:00:00 +0200 41 | """ 42 | cl = ChangeLog(changes) 43 | self.assertEqual(cl.author, 'User Nme') 44 | self.assertEqual(cl.email, 'agx@sigxcpu.org') 45 | self.assertEqual('\0' in cl.get_changes(), False) 46 | 47 | 48 | @skip_without_cmd('debchange') 49 | class Test(unittest.TestCase): 50 | def setUp(self): 51 | self.tmpdir = context.new_tmpdir(__name__) 52 | context.chdir(self.tmpdir) 53 | os.mkdir('debian/') 54 | 55 | def tearDown(self): 56 | context.teardown() 57 | 58 | def test_changelog_creation_full(self): 59 | cp = ChangeLog.create('package', '1.0') 60 | self.assertEqual(cp.name, 'package') 61 | self.assertEqual(cp.version, '1.0') 62 | 63 | def test_changelog_creation_version(self): 64 | cp = ChangeLog.create(version='1.0') 65 | self.assertEqual(cp.name, 'PACKAGE') 66 | self.assertEqual(cp.version, '1.0') 67 | 68 | def test_changelog_creation_package(self): 69 | cp = ChangeLog.create(package='package') 70 | self.assertEqual(cp.name, 'package') 71 | self.assertEqual(cp.version, 'unknown') 72 | 73 | def test_changelog_missing_dir(self): 74 | os.rmdir('debian/') 75 | with self.assertRaisesRegex(CommandExecFailed, "Cannot find debian directory"): 76 | ChangeLog.create('package', '1.0') 77 | 78 | def test_changelog_exists(self): 79 | with open('debian/changelog', 'w') as f: 80 | f.write('') 81 | with self.assertRaisesRegex(CommandExecFailed, "File debian/changelog already exists"): 82 | ChangeLog.create('package', '1.0') 83 | -------------------------------------------------------------------------------- /tests/31_test_uscan.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """Test L{gbp.deb}""" 4 | 5 | from . import context # noqa: F401 6 | from . import testutils 7 | 8 | import unittest 9 | 10 | from gbp.deb.uscan import Uscan 11 | 12 | 13 | class TestUscan(unittest.TestCase): 14 | """Test L{gbp.deb.uscan}""" 15 | 16 | uscan_ok = b""" 17 | uscan: Newest version of virt-what on remote site is 1.18, local version is 1.15 18 | uscan: => Newer package available from 19 | https://people.redhat.com/~rjones/virt-what/files/virt-what-1.18.tar.gz 20 | gpgv: Signature made Mo 31 Jul 2017 11:36:08 ADT 21 | gpgv: using RSA key 91738F73E1B768A0 22 | gpgv: Good signature from "Richard W.M. Jones " 23 | gpgv: aka "Richard W.M. Jones " 24 | virt-what 25 | 1.15 26 | 1.15 27 | 1.18 28 | https://people.redhat.com/~rjones/virt-what/files/virt-what-1.18.tar.gz 29 | newer package available 30 | virt-what_1.18.orig.tar.gz 31 | ../virt-what_1.18.orig.tar.gz 32 | Not downloading, using existing file: virt-what-1.18.tar.gz 33 | 34 | Leaving ../virt-what_1.18.orig.tar.gz where it is. 35 | 36 | """ 37 | 38 | @testutils.patch_popen(stdout=uscan_ok, stderr=b'', returncode=0) 39 | def test_uscan(self, uscan_mock): 40 | """Test parsing a valid uscan file""" 41 | uscan = Uscan() 42 | self.assertTrue(uscan.scan()) 43 | self.assertFalse(uscan.uptodate) 44 | self.assertEqual(uscan.tarball, '../virt-what_1.18.orig.tar.gz') 45 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2009, 2010,2011, 2012 Guido Günther 4 | # (C) 2012 Intel Corporation 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | """Unit tests for git-buildpackage""" 19 | 20 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 21 | -------------------------------------------------------------------------------- /tests/component/deb/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012 Intel Corporation 4 | # (C) 2013 Guido Günther 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, please see 18 | # 19 | 20 | import os 21 | 22 | from tests.component import ComponentTestGitRepository 23 | 24 | DEB_TEST_SUBMODULE = os.path.join('tests', 'component', 'deb', 'data') 25 | DEB_TEST_DATA_DIR = os.path.abspath(DEB_TEST_SUBMODULE) 26 | DEB_TEST_DOWNLOAD_URL = 'https://git.sigxcpu.org/cgit/gbp/deb-testdata/plain/' 27 | 28 | 29 | def setup_module(): 30 | """Test Module setup""" 31 | ComponentTestGitRepository.check_testdata(DEB_TEST_SUBMODULE) 32 | -------------------------------------------------------------------------------- /tests/component/deb/test_dch.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2017 Guido Günther 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | 19 | import os 20 | 21 | from tests.component import ComponentTestBase 22 | from tests.component.deb import DEB_TEST_DATA_DIR 23 | from tests.component.deb.fixtures import RepoFixtures 24 | from tests.testutils import skip_without_cmd 25 | 26 | import gbp.scripts.dch 27 | from gbp.scripts.dch import main as dch 28 | 29 | 30 | def _dsc_file(pkg, version, dir='dsc-3.0'): 31 | return os.path.join(DEB_TEST_DATA_DIR, dir, '%s_%s.dsc' % (pkg, version)) 32 | 33 | 34 | DEFAULT_DSC = _dsc_file('hello-debhelper', '2.6-2') 35 | 36 | 37 | @skip_without_cmd('debchange') 38 | class TestDch(ComponentTestBase): 39 | """Test importing of new upstream versions""" 40 | pkg = "hello-debhelper" 41 | def_branches = ['master', 'upstream', 'pristine-tar'] 42 | 43 | @RepoFixtures.quilt30(DEFAULT_DSC) 44 | def test_user_customizations(self, repo): 45 | os.chdir(repo.path) 46 | # Non-existent customization file 47 | assert ( 48 | dch(["arg0", "--customizations=customizations.py"]) == 1 49 | ), "dch did no fail as expected" 50 | 51 | # Create user customizations file 52 | with open('customizations.py', 'w') as fobj: 53 | fobj.write("""def format_changelog_entry(commit_info, options, last_commit=False): 54 | return ['testentry'] 55 | """) 56 | # Add the file so we have a change 57 | repo.add_files(['customizations.py']) 58 | repo.commit_all(msg="test customizations") 59 | assert ( 60 | dch(["arg0", "-S", "-a", "--customizations=customizations.py"]) == 0 61 | ), "dch did no succeed as expected" 62 | with open("debian/changelog", encoding="utf-8") as f: 63 | cl = f.read() 64 | assert "* testentry\n" in cl 65 | del gbp.scripts.dch.user_customizations["format_changelog_entry"] 66 | 67 | @RepoFixtures.native() 68 | def test_postedit_hook(self, repo): 69 | os.chdir(repo.path) 70 | assert dch(["arg0", "-N", "1.2.3", "--postedit", "echo $GBP_DEBIAN_VERSION > foo.txt"]) == 0 71 | with open("foo.txt") as f: 72 | assert f.read() == "1.2.3\n" 73 | -------------------------------------------------------------------------------- /tests/component/deb/test_import_dscs.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2017 Guido Günther 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | 19 | import os 20 | 21 | from tests.component import (ComponentTestBase, 22 | ComponentTestGitRepository) 23 | from tests.component.deb import DEB_TEST_DATA_DIR 24 | 25 | from gbp.scripts.import_dscs import main as import_dscs 26 | 27 | 28 | class TestImportDscs(ComponentTestBase): 29 | """Test importing of debian source packages""" 30 | 31 | def test_import_debian_native(self): 32 | """Test that importing of debian native packages works""" 33 | def _dsc(version): 34 | return os.path.join(DEB_TEST_DATA_DIR, 35 | 'dsc-native', 36 | 'git-buildpackage_%s.dsc' % version) 37 | 38 | dsc1 = _dsc('0.4.14') 39 | dsc2 = _dsc('0.4.15') 40 | assert import_dscs(['arg0', dsc1, dsc2]) == 0 41 | repo = ComponentTestGitRepository('git-buildpackage') 42 | self._check_repo_state(repo, 'master', ['master']) 43 | assert len(repo.get_commits()) == 2 44 | commitmsg = repo.get_commit_info('HEAD')['body'] 45 | assert "git-buildpackage (0.4.15) unstable; urgency=low" in commitmsg 46 | -------------------------------------------------------------------------------- /tests/component/deb/test_tag.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2015-2017 Guido Günther 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, please see 17 | # 18 | 19 | import os 20 | 21 | from tests.component import ComponentTestBase 22 | from tests.component.deb import DEB_TEST_DATA_DIR 23 | from tests.component.deb.fixtures import RepoFixtures 24 | 25 | from gbp.scripts.tag import main as tag 26 | from gbp.scripts.pq import main as pq 27 | 28 | 29 | class TestTag(ComponentTestBase): 30 | """Test tagging a debian package""" 31 | 32 | @staticmethod 33 | def _dsc_name(pkg, version, dir): 34 | return os.path.join(DEB_TEST_DATA_DIR, 35 | dir, 36 | '%s_%s.dsc' % (pkg, version)) 37 | 38 | @RepoFixtures.native() 39 | def test_tag(self, repo): 40 | """Test that tagging a native debian package works""" 41 | repo.delete_tag("debian/0.4.14") # make sure we can tag again 42 | assert repo.has_tag("debian/0.4.14") is False 43 | ret = tag(["arg0", "--posttag=printenv > posttag.out"]) 44 | assert ret == 0, "Tagging the package failed" 45 | assert os.path.exists("posttag.out") is True 46 | self.check_hook_vars( 47 | "posttag", [("GBP_TAG", "debian/0.4.14"), ("GBP_BRANCH", "master"), "GBP_SHA1"] 48 | ) 49 | assert repo.head == repo.rev_parse("debian/0.4.14^{}") 50 | 51 | @RepoFixtures.quilt30() 52 | def test_tag_pq_branch(self, repo): 53 | ret = pq(["argv0", "import"]) 54 | assert repo.rev_parse("master") == repo.rev_parse("debian/2.8-1^{}") 55 | assert ret == 0 56 | assert repo.branch == "patch-queue/master" 57 | self.add_file(repo, "foo.txt") 58 | ret = tag(["argv0", "--retag", "--ignore-branch"]) 59 | assert ret == 0 60 | assert repo.branch == "patch-queue/master" 61 | assert repo.rev_parse("patch-queue/master^{}^") == repo.rev_parse("debian/2.8-1^{}") 62 | 63 | @RepoFixtures.quilt30() 64 | def test_tag_detached_head(self, repo): 65 | """ 66 | Test that tagging works with an detached head (#863167) 67 | """ 68 | assert repo.rev_parse("master^{}") == repo.rev_parse("debian/2.8-1^{}") 69 | self.add_file(repo, "debian/foo.txt") 70 | repo.checkout("HEAD~") 71 | ret = tag(['argv0', '--retag', '--ignore-branch']) 72 | assert ret == 0 73 | repo.checkout("master") 74 | assert repo.rev_parse("master~^{}") == repo.rev_parse("debian/2.8-1^{}") 75 | -------------------------------------------------------------------------------- /tests/component/rpm/__init__.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2012 Intel Corporation 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | """Test module for RPM command line tools of the git-buildpackage suite""" 18 | 19 | import os 20 | import shutil 21 | from glob import glob 22 | 23 | from gbp.command_wrappers import Command 24 | 25 | from tests.component import ComponentTestBase, ComponentTestGitRepository 26 | 27 | 28 | RPM_TEST_DATA_SUBMODULE = os.path.join('tests', 'component', 'rpm', 'data') 29 | RPM_TEST_DATA_DIR = os.path.abspath(RPM_TEST_DATA_SUBMODULE) 30 | 31 | 32 | def setup_module(): 33 | """Test Module setup""" 34 | ComponentTestGitRepository.check_testdata(RPM_TEST_DATA_SUBMODULE) 35 | 36 | 37 | class RpmRepoTestBase(ComponentTestBase): 38 | """Baseclass for tests run in a Git repository with packaging data""" 39 | 40 | @classmethod 41 | def setUpClass(cls): 42 | """Initializations only made once per test run""" 43 | super(RpmRepoTestBase, cls).setUpClass() 44 | 45 | # Initialize test data repositories 46 | cmd = Command('./manage.py', cwd=RPM_TEST_DATA_DIR, capture_stderr=True) 47 | cmd(['import-repo', '-o', cls._tmproot]) 48 | 49 | cls.orig_repos = {} 50 | for path in glob(cls._tmproot + '/*.repo'): 51 | prj = os.path.basename(path).rsplit('.', 1)[0] 52 | cls.orig_repos[prj] = ComponentTestGitRepository(path) 53 | 54 | @classmethod 55 | def init_test_repo(cls, pkg_name): 56 | """Initialize git repository for testing""" 57 | dirname = os.path.basename(cls.orig_repos[pkg_name].path) 58 | shutil.copytree(cls.orig_repos[pkg_name].path, dirname) 59 | os.chdir(dirname) 60 | return ComponentTestGitRepository('.') 61 | 62 | init_test_repo.__test__ = False 63 | 64 | # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: 65 | -------------------------------------------------------------------------------- /tests/context.py: -------------------------------------------------------------------------------- 1 | # this context.py should be included by all tests 2 | # idea from http://kennethreitz.com/repository-structure-and-python.html 3 | 4 | import os 5 | import shutil 6 | import sys 7 | import tempfile 8 | 9 | sys.path.insert(0, os.path.abspath('..')) 10 | 11 | import gbp # noqa: E402 12 | import gbp.log # noqa: E402 13 | 14 | gbp.log.setup(False, False) 15 | 16 | 17 | # the top or root dir of the git-buildpackage source tree to be used by tests 18 | projectdir = os.path.dirname(os.path.dirname(os.path.abspath(gbp.__file__))) 19 | 20 | _chdir_backup = None 21 | _tmpdirs = [] 22 | 23 | 24 | def chdir(dir): 25 | global _chdir_backup 26 | if not _chdir_backup: 27 | _chdir_backup = os.path.abspath(os.curdir) 28 | os.chdir(str(dir)) 29 | 30 | 31 | def new_tmpdir(name): 32 | global _tmpdirs 33 | prefix = 'gbp_%s_' % name 34 | tmpdir = TmpDir(prefix) 35 | _tmpdirs.append(tmpdir) 36 | return tmpdir 37 | 38 | 39 | def teardown(): 40 | if _chdir_backup: 41 | os.chdir(_chdir_backup) 42 | for tmpdir in _tmpdirs: 43 | tmpdir.rmdir() 44 | del _tmpdirs[:] 45 | 46 | 47 | class TmpDir(object): 48 | 49 | def __init__(self, suffix='', prefix='tmp'): 50 | self.path = tempfile.mkdtemp(suffix=suffix, prefix=prefix) 51 | 52 | def rmdir(self): 53 | if self.path and not os.getenv("GBP_TESTS_NOCLEAN"): 54 | shutil.rmtree(self.path) 55 | self.path = None 56 | 57 | def __repr__(self): 58 | return self.path 59 | 60 | def join(self, *args): 61 | return os.path.join(self.path, *args) 62 | -------------------------------------------------------------------------------- /tests/data/brackets-in-subject.patch: -------------------------------------------------------------------------------- 1 | From: Guido Günther 2 | Subject: [text] foobar 3 | 4 | foo 5 | 6 | diff --git a/foo b/foo 7 | new file mode 100644 8 | index 0000000..257cc56 9 | --- /dev/null 10 | +++ b/foo 11 | @@ -0,0 +1 @@ 12 | +foo 13 | -------------------------------------------------------------------------------- /tests/data/foo.patch: -------------------------------------------------------------------------------- 1 | From: Guido Günther 2 | Subject: foobar 3 | 4 | foo 5 | 6 | diff --git a/foo b/foo 7 | new file mode 100644 8 | index 0000000..257cc56 9 | --- /dev/null 10 | +++ b/foo 11 | @@ -0,0 +1 @@ 12 | +foo 13 | -------------------------------------------------------------------------------- /tests/data/gbp_config.conf: -------------------------------------------------------------------------------- 1 | # Data for TestGbpConfig 2 | 3 | [config] 4 | color-scheme = checkcheck 5 | -------------------------------------------------------------------------------- /tests/data/gbp_create_remote_repo.conf: -------------------------------------------------------------------------------- 1 | # Data for TestGbpCreateRemoteRepo 2 | 3 | [remote-config config1] 4 | remote-url-pattern = ssh://git.debian.org/git/pkg-libvirt/%(pkg)s.git 5 | template-dir = /srv/alioth.debian.org/chroot/home/groups/pkg-libvirt/git-template 6 | 7 | [remote-config config2] 8 | remote-url-pattern = ssh://git.debian.org/git/calendarserver/%(pkg)s.git 9 | -------------------------------------------------------------------------------- /tests/data/pristine_tar/testfile1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/pristine_tar/testfile1 -------------------------------------------------------------------------------- /tests/data/pristine_tar/testfile2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/pristine_tar/testfile2 -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/bar.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/rpmbuild/SOURCES/bar.tar.gz -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/foo.txt: -------------------------------------------------------------------------------- 1 | FOO: 2 | 3 | file for testing rpm support of git-buildpackage. 4 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2 -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zip -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gz -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/my.patch: -------------------------------------------------------------------------------- 1 | diff --git a/dummy.sh b/dummy.sh 2 | index 8c33db6..6f04268 100755 3 | --- dummy.sh 4 | +++ dummy.sh 5 | @@ -1,3 +1,3 @@ 6 | #!/bin/sh 7 | 8 | -echo "Hello world" 9 | +echo "Hello GBP" 10 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/my2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/mydir/myfile.txt b/mydir/myfile.txt 2 | new file mode 100644 3 | index 0000000..2cdad29 4 | --- /dev/null 5 | +++ b/mydir/myfile.txt 6 | @@ -0,0 +1 @@ 7 | +Dummy 8 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SOURCES/my3.patch: -------------------------------------------------------------------------------- 1 | diff --git a/README b/README 2 | index a1311cb..a59f1b9 100644 3 | --- a/README 4 | +++ b/README 5 | @@ -1 +1 @@ 6 | -Just for testing git-buildpackage. 7 | +Just for testing GBP. 8 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SPECS/gbp-test-native.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test-native 2 | Summary: Test package for git-buildpackage 3 | Version: 1.0 4 | Release: 1 5 | Group: Development/Libraries 6 | License: GPLv2 7 | Source1: %{name}-%{version}.zip 8 | BuildRequires: unzip 9 | 10 | %description 11 | Package for testing the RPM functionality of git-buildpackage. 12 | Mimics a "native" package 13 | 14 | 15 | %prep 16 | unzip %{SOURCE1} 17 | %setup -T -D 18 | 19 | 20 | %build 21 | make 22 | 23 | 24 | %install 25 | rm -rf %{buildroot} 26 | mkdir -p %{buildroot}/%{_datadir}/%{name} 27 | cp -R * %{buildroot}/%{_datadir}/%{name} 28 | 29 | 30 | 31 | %files 32 | %defattr(-,root,root,-) 33 | %dir %{_datadir}/%{name} 34 | %{_datadir}/%{name} 35 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SPECS/gbp-test-native2.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test-native2 2 | Summary: Test package for git-buildpackage 3 | Version: 2.0 4 | Release: 0 5 | Group: Development/Libraries 6 | License: GPLv2 7 | Source: foo.txt 8 | BuildRequires: unzip 9 | 10 | %description 11 | Package for testing the RPM functionality of git-buildpackage. 12 | Mimics a "native" package that doesn't have any source tarball. 13 | 14 | 15 | %prep 16 | # Just create build dir 17 | %setup -T -c 18 | cp %{SOURCE0} . 19 | 20 | 21 | %build 22 | # Nothing to do 23 | 24 | 25 | %install 26 | rm -rf %{buildroot} 27 | mkdir -p %{buildroot}/%{_datadir}/%{name} 28 | cp -R * %{buildroot}/%{_datadir}/%{name} 29 | 30 | 31 | 32 | %files 33 | %defattr(-,root,root,-) 34 | %dir %{_datadir}/%{name} 35 | %{_datadir}/%{name} 36 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SPECS/gbp-test.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test 2 | Summary: Test package for git-buildpackage 3 | Version: 1.0 4 | Release: 1 5 | Group: Development/Libraries 6 | License: GPLv2 7 | Source: %{name}-%{version}.tar.bz2 8 | Source1: foo.txt 9 | Source20: bar.tar.gz 10 | # Gbp-Ignore-Patches: 0 11 | Patch0: my.patch 12 | Patch10: my2.patch 13 | Patch20: my3.patch 14 | 15 | 16 | %description 17 | Package for testing the RPM functionality of git-buildpackage. 18 | 19 | 20 | %prep 21 | %setup -n %{name} -a 20 22 | 23 | %patch0 24 | %patch10 -p1 25 | 26 | 27 | %build 28 | make 29 | 30 | 31 | %install 32 | rm -rf %{buildroot} 33 | mkdir -p %{buildroot}/%{_datadir}/%{name} 34 | cp -R * %{buildroot}/%{_datadir}/%{name} 35 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 36 | 37 | 38 | 39 | %files 40 | %defattr(-,root,root,-) 41 | %dir %{_datadir}/%{name} 42 | %{_datadir}/%{name} 43 | -------------------------------------------------------------------------------- /tests/data/rpm/rpmbuild/SPECS/gbp-test2.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test2 2 | Summary: Test package 2 for git-buildpackage 3 | Epoch: 2 4 | Version: 3.0 5 | Release: 0 6 | Group: Development/Libraries 7 | License: GPLv2 8 | Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz 9 | Source0: foo.txt 10 | Source20: bar.tar.gz 11 | # Gbp-Ignore-Patches: 0 12 | Patch0: my.patch 13 | Patch10: my2.patch 14 | Patch20: my3.patch 15 | Packager: Markus Lehtonen 16 | VCS: myoldvcstag 17 | 18 | %description 19 | Package for testing the RPM functionality of git-buildpackage. 20 | 21 | %package empty 22 | Summary: Empty subpackage 23 | 24 | %description empty 25 | Empty subpackage for the %{name} test package. 26 | 27 | 28 | %prep 29 | %setup -T -n %{name}-%{version} -c -a 10 30 | 31 | %patch 32 | %patch -P 10 -p1 33 | 34 | echo "Do things" 35 | 36 | # Gbp-Patch-Macros 37 | 38 | %build 39 | make 40 | 41 | 42 | %install 43 | rm -rf %{buildroot} 44 | mkdir -p %{buildroot}/%{_datadir}/%{name} 45 | cp -R * %{buildroot}/%{_datadir}/%{name} 46 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 47 | 48 | 49 | %changelog 50 | * Tue Feb 04 2014 Name 1 51 | - My change 52 | 53 | 54 | %files 55 | %defattr(-,root,root,-) 56 | %dir %{_datadir}/%{name} 57 | %{_datadir}/%{name} 58 | 59 | %files empty 60 | %defattr(-,root,root,-) 61 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-native.spec: -------------------------------------------------------------------------------- 1 | ../rpmbuild/SPECS/gbp-test-native.spec -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-native2.spec: -------------------------------------------------------------------------------- 1 | ../rpmbuild/SPECS/gbp-test-native2.spec -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-quirks.spec: -------------------------------------------------------------------------------- 1 | # 2 | # Spec for testing some quirks of spec parsing 3 | # 4 | 5 | Name: pkg_name 6 | Summary: Spec for testing some quirks of spec parsing 7 | Version: 0.1 8 | Release: 1.2 9 | License: GPLv2 10 | Source1: foobar.tar.gz 11 | # Gbp-Ignore-Patches: 2 4 888 12 | Patch1: 01.patch 13 | Patch2: 02.patch 14 | Patch3: 03.patch 15 | Patch4: 04.patch 16 | Patch5: 05.patch 17 | 18 | %description 19 | Spec for testing some quirks of spec parsing. No intended for building an RPM. 20 | 21 | %prep 22 | # We don't have Source0 so rpmbuild would fail, but gbp shouldn't crash 23 | %setup -q 24 | 25 | # Patches are applied out-of-order wrt. numbering 26 | %patch5 27 | %patch2 28 | %patch1 -F2 29 | # Patch 999 does not exist, rpmbuild would fail but GBP should not 30 | %patch999 31 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-reference.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test 2 | Summary: Test package for git-buildpackage 3 | Version: 1.0 4 | Release: 1 5 | Group: Development/Libraries 6 | License: GPLv2 7 | Source: %{name}-%{version}.tar.bz2 8 | Source1: foo.txt 9 | Source20: bar.tar.gz 10 | # Gbp-Ignore-Patches: 0 11 | Patch0: my.patch 12 | # Patches auto-generated by git-buildpackage: 13 | Patch1: new.patch 14 | 15 | 16 | %description 17 | Package for testing the RPM functionality of git-buildpackage. 18 | 19 | 20 | %prep 21 | %setup -n %{name} -a 20 22 | 23 | %patch0 24 | # new.patch 25 | %patch1 -p1 26 | 27 | 28 | %build 29 | make 30 | 31 | 32 | %install 33 | rm -rf %{buildroot} 34 | mkdir -p %{buildroot}/%{_datadir}/%{name} 35 | cp -R * %{buildroot}/%{_datadir}/%{name} 36 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 37 | 38 | 39 | 40 | %files 41 | %defattr(-,root,root,-) 42 | %dir %{_datadir}/%{name} 43 | %{_datadir}/%{name} 44 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-reference2.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test 2 | VCS: myvcstag 3 | Summary: Test package for git-buildpackage 4 | Version: 1.0 5 | Release: 1 6 | Group: Development/Libraries 7 | License: GPLv2 8 | Source: %{name}-%{version}.tar.bz2 9 | Source1: foo.txt 10 | Source20: bar.tar.gz 11 | # Gbp-Ignore-Patches: 0 12 | Patch0: my.patch 13 | # Patches auto-generated by git-buildpackage: 14 | Patch1: new.patch 15 | 16 | 17 | %description 18 | Package for testing the RPM functionality of git-buildpackage. 19 | 20 | 21 | %prep 22 | %setup -n %{name} -a 20 23 | 24 | %patch0 25 | # new.patch 26 | %patch1 -p1 27 | 28 | 29 | %build 30 | make 31 | 32 | 33 | %install 34 | rm -rf %{buildroot} 35 | mkdir -p %{buildroot}/%{_datadir}/%{name} 36 | cp -R * %{buildroot}/%{_datadir}/%{name} 37 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 38 | 39 | 40 | 41 | %files 42 | %defattr(-,root,root,-) 43 | %dir %{_datadir}/%{name} 44 | %{_datadir}/%{name} 45 | %changelog 46 | * Wed Feb 05 2014 Name 1 47 | - New entry 48 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-tags.spec: -------------------------------------------------------------------------------- 1 | # 2 | # Spec file for testing all RPM tags (that we know of 3 | # 4 | 5 | %define suse_release %(test -e /etc/SuSE-release && head -n1 /etc/SuSE-release | cut -d ' ' -f2 | cut --output-delimiter=0 -d. -f1,2 || echo 0) 6 | %if "%{suse_release}" >= "1201" 7 | %define test_weak_dep_tags 1 8 | %if "%{suse_release}" < "1302" 9 | %define test_weak_dep_tags_2 1 10 | %endif 11 | %endif 12 | 13 | %define test_arch_os_tags %(test -n "$GBP_SKIP_ARCH_OS_TAGS" && echo 0 || echo 1) 14 | 15 | %define source_fn_base source 16 | %define patch_fn_base patch 17 | 18 | # Gbp-Undefined-Tag: foobar 19 | 20 | # Test that we accept different cases 21 | NAME: my_name 22 | version: 0 23 | ReLeasE: 0 24 | 25 | # Rest of the tags 26 | Epoch: 0 27 | Summary: my_summary 28 | License: my_license 29 | Distribution: my_distribution 30 | Vendor: my_vendor 31 | Group: my_group 32 | Packager: my_packager 33 | Url: my_url 34 | Vcs: my_vcs 35 | Source: my_source 36 | Patch1: my_%patch_fn_base 37 | Patch0: my_%{patch_fn_base}0 38 | Nosource: 0 39 | Nopatch: 0 40 | #Icon: my_icon 41 | BuildRoot: my_buildroot 42 | Provides: my_provides 43 | Requires: my_requires 44 | Conflicts: my_conflicts 45 | Obsoletes: my_obsoletes 46 | BuildConflicts: my_buildconflicts 47 | BuildRequires: my_buildrequires 48 | AutoReqProv: No 49 | AutoReq: No 50 | AutoProv: No 51 | DistTag: my_disttag 52 | BugUrl: my_bugurl 53 | 54 | %if 0%{?test_weak_dep_tags} 55 | Recommends: my_recommends 56 | Suggests: my_suggests 57 | Supplements: my_supplements 58 | Enhances: my_enhances 59 | %if 0%{?test_weak_dep_tags_2} 60 | BuildRecommends:my_buildrecommends 61 | BuildSuggests: my_buildsuggests 62 | BuildSupplements:my_buildsupplements 63 | BuildEnhances: my_buildenhances 64 | %endif 65 | %endif 66 | 67 | # These should be filtered out by GBP 68 | %if "%{test_arch_os_tags}" != "0" 69 | BuildArch: my_buildarch 70 | ExcludeArch: my_excludearch 71 | ExclusiveArch: my_exclusivearch 72 | ExcludeOs: my_excludeos 73 | ExclusiveOs: my_exclusiveos 74 | %endif 75 | 76 | %description 77 | Package for testing GBP. 78 | 79 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-updates-reference.spec: -------------------------------------------------------------------------------- 1 | # 2 | # Spec file for testing deleting/adding/updating tags and macros 3 | # 4 | 5 | # Gbp-Undefined-Tag: foobar 6 | 7 | # Test that we accept different cases 8 | Name: my_name 9 | Version: 0 10 | Release: 1 11 | Summary: my_summary 12 | License: new license 13 | Distribution: my_distribution 14 | Group: my_group 15 | Packager: my_packager 16 | Url: my_url 17 | Vcs: my_vcs 18 | Nosource: 0 19 | Nopatch: 0 20 | BuildRoot: my_buildroot 21 | Provides: my_provides 22 | Requires: my_requires 23 | Conflicts: my_conflicts 24 | Obsoletes: my_obsoletes 25 | BuildConflicts: my_buildconflicts 26 | BuildRequires: my_buildrequires 27 | AutoReqProv: No 28 | AutoReq: No 29 | AutoProv: No 30 | DistTag: my_disttag 31 | BugUrl: my_bugurl 32 | 33 | %description 34 | Package for testing GBP. 35 | 36 | %prep 37 | %setup -n my_prefix 38 | 39 | %patch0 my new args 40 | 41 | %build 42 | 43 | %install 44 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test-updates.spec: -------------------------------------------------------------------------------- 1 | # 2 | # Spec file for testing deleting/adding/updating tags and macros 3 | # 4 | 5 | # Gbp-Undefined-Tag: foobar 6 | 7 | # Test that we accept different cases 8 | Name: my_name 9 | Version: 0 10 | Release: 1 11 | Summary: my_summary 12 | License: my_license 13 | Distribution: my_distribution 14 | Vendor: my_vendor 15 | Group: my_group 16 | Packager: my_packager 17 | Url: my_url 18 | Vcs: my_vcs 19 | Source: my_source 20 | Patch1: my_%patch_fn_base 21 | Patch0: my_%{patch_fn_base}0 22 | Nosource: 0 23 | Nopatch: 0 24 | BuildRoot: my_buildroot 25 | Provides: my_provides 26 | Requires: my_requires 27 | Conflicts: my_conflicts 28 | Obsoletes: my_obsoletes 29 | BuildConflicts: my_buildconflicts 30 | BuildRequires: my_buildrequires 31 | AutoReqProv: No 32 | AutoReq: No 33 | AutoProv: No 34 | DistTag: my_disttag 35 | BugUrl: my_bugurl 36 | 37 | %description 38 | Package for testing GBP. 39 | 40 | %prep 41 | %setup -n my_prefix 42 | 43 | %patch -b my_patch 44 | %patch -P0 -b my_patch0 45 | 46 | %build 47 | 48 | %install 49 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test.spec: -------------------------------------------------------------------------------- 1 | ../rpmbuild/SPECS/gbp-test.spec -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test2-reference.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test2 2 | Summary: Test package 2 for git-buildpackage 3 | Epoch: 2 4 | Version: 3.0 5 | Release: 0 6 | Group: Development/Libraries 7 | License: GPLv2 8 | Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz 9 | Source0: foo.txt 10 | Source20: bar.tar.gz 11 | # Gbp-Ignore-Patches: 0 12 | Patch0: my.patch 13 | # Patches auto-generated by git-buildpackage: 14 | Patch1: new.patch 15 | Packager: Markus Lehtonen 16 | 17 | %description 18 | Package for testing the RPM functionality of git-buildpackage. 19 | 20 | %package empty 21 | Summary: Empty subpackage 22 | 23 | %description empty 24 | Empty subpackage for the %{name} test package. 25 | 26 | 27 | %prep 28 | %setup -T -n %{name}-%{version} -c -a 10 29 | 30 | 31 | echo "Do things" 32 | 33 | # Gbp-Patch-Macros 34 | # new.patch 35 | %if 1 36 | %patch1 -p1 37 | %endif 38 | 39 | %build 40 | make 41 | 42 | 43 | %install 44 | rm -rf %{buildroot} 45 | mkdir -p %{buildroot}/%{_datadir}/%{name} 46 | cp -R * %{buildroot}/%{_datadir}/%{name} 47 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 48 | 49 | 50 | %changelog 51 | * Wed Feb 05 2014 Name 2 52 | - New entry 53 | 54 | %files 55 | %defattr(-,root,root,-) 56 | %dir %{_datadir}/%{name} 57 | %{_datadir}/%{name} 58 | 59 | %files empty 60 | %defattr(-,root,root,-) 61 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test2-reference2.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test2 2 | Summary: Test package 2 for git-buildpackage 3 | Epoch: 2 4 | Version: 3.0 5 | Release: 0 6 | Group: Development/Libraries 7 | License: GPLv2 8 | Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz 9 | Source0: foo.txt 10 | Source20: bar.tar.gz 11 | # Gbp-Ignore-Patches: 0 12 | Patch0: my.patch 13 | # Patches auto-generated by git-buildpackage: 14 | Patch1: 1.patch 15 | Patch2: 2.patch 16 | Packager: Markus Lehtonen 17 | VCS: myvcstag 18 | 19 | %description 20 | Package for testing the RPM functionality of git-buildpackage. 21 | 22 | %package empty 23 | Summary: Empty subpackage 24 | 25 | %description empty 26 | Empty subpackage for the %{name} test package. 27 | 28 | 29 | %prep 30 | %setup -T -n %{name}-%{version} -c -a 10 31 | 32 | 33 | echo "Do things" 34 | 35 | # Gbp-Patch-Macros 36 | # 1.patch 37 | %if true 38 | %patch1 -p1 39 | %endif 40 | # 2.patch 41 | %ifarch %ix86 42 | %patch2 -p1 43 | %endif 44 | 45 | %build 46 | make 47 | 48 | 49 | %install 50 | rm -rf %{buildroot} 51 | mkdir -p %{buildroot}/%{_datadir}/%{name} 52 | cp -R * %{buildroot}/%{_datadir}/%{name} 53 | install %{SOURCE0} %{buildroot}/%{_datadir}/%{name} 54 | 55 | 56 | %changelog 57 | * Tue Feb 04 2014 Name 1 58 | - My change 59 | 60 | 61 | %files 62 | %defattr(-,root,root,-) 63 | %dir %{_datadir}/%{name} 64 | %{_datadir}/%{name} 65 | 66 | %files empty 67 | %defattr(-,root,root,-) 68 | -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test2.spec: -------------------------------------------------------------------------------- 1 | ../rpmbuild/SPECS/gbp-test2.spec -------------------------------------------------------------------------------- /tests/data/rpm/specs/gbp-test3.spec: -------------------------------------------------------------------------------- 1 | Name: gbp-test3 2 | Summary: Test package 3 for git-buildpackage 3 | Version: 1.0 4 | Release: 0 5 | Group: Development/Libraries 6 | License: GPLv2 7 | Source: %{name}-%{version}.tar.gz 8 | # Gbp-Ignore-Patches: 10 9 | Patch0: my.patch 10 | Patch10: my2.patch 11 | Patch20: my3.patch 12 | 13 | %description 14 | Another test package for git-buildpackage. 15 | 16 | 17 | %prep 18 | %autosetup -n %{name}-%{version} 19 | 20 | 21 | %build 22 | make 23 | 24 | 25 | %install 26 | mkdir -p %{buildroot}/%{_datadir}/%{name} 27 | 28 | 29 | %files 30 | %defattr(-,root,root,-) 31 | %dir %{_datadir}/%{name} 32 | %{_datadir}/%{name} 33 | -------------------------------------------------------------------------------- /tests/data/rpm/srpms/gbp-test-1.0-1.src.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/srpms/gbp-test-1.0-1.src.rpm -------------------------------------------------------------------------------- /tests/data/rpm/srpms/gbp-test2-3.0-0.src.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/data/rpm/srpms/gbp-test2-3.0-0.src.rpm -------------------------------------------------------------------------------- /tests/data/test1.conf: -------------------------------------------------------------------------------- 1 | # Data for TestConfigParser 2 | 3 | [DEFAULT] 4 | default_option = default_default1 5 | single_override_option1 = single_override_default1 6 | single_git_override_option1 = single_git_override_default1 7 | single_gbp_override_option1 = single_gbp_override_default1 8 | new_overrides_git_option1 = new_overrides_git_default1 9 | 10 | # These commands only have a single section overriding defaults. 11 | # There are no alterntive old or new names 12 | [cmd1] 13 | single_override_option1 = single_override_value1 14 | 15 | [git-cmd2] 16 | single_git_override_option1 = single_git_override_value1 17 | 18 | [gbp-cmd3] 19 | single_gbp_override_option1 = single_gbp_override_value1 20 | 21 | # This commands have a new name overriding the old git- section 22 | # The order of the sections differs though 23 | [git-cmd4] 24 | new_overrides_git_option1 = new_overrides_git_overridden1 25 | 26 | [cmd4] 27 | new_overrides_git_option1 = new_overrides_git_value1 28 | 29 | [cmd5] 30 | new_overrides_git_option1 = new_overrides_git_value1 31 | 32 | [git-cmd5] 33 | new_overrides_git_option1 = new_overrides_git_overridden1 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/doctests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agx/git-buildpackage/859d9d60aa894f5e4feb0e44a903be5dcc476268/tests/doctests/__init__.py -------------------------------------------------------------------------------- /tests/doctests/test_Control.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """ 4 | Test L{gbp.deb.control.Control} 5 | """ 6 | 7 | from .. import context # noqa: F401 8 | 9 | cl_debian = """Source: git-buildpackage 10 | Section: vcs 11 | Priority: optional 12 | Maintainer: Guido Günther 13 | Build-Depends: debhelper (>= 7.0.50~), python (>> 2.6.6-3~), 14 | pychecker, gtk-doc-tools, sgml2x, docbook-utils, jade, python-dateutil, python-nose, 15 | bash-completion, perl, python-epydoc, python-coverage, python-setuptools, 16 | # For the testsuite 17 | git (>= 1:1.7.9.1-1~), bzip2, unzip, pristine-tar 18 | Standards-Version: 3.9.3 19 | Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git 20 | Vcs-Browser: http://git.debian.org/?p=users/agx/git-buildpackage.git 21 | Homepage: https://honk.sigxcpu.org/piki/projects/git-buildpackage/ 22 | X-Python-Version: >= 2.6 23 | 24 | Package: git-buildpackage 25 | Architecture: all 26 | Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, devscripts (>= 2.10.66~), 27 | git (>= 1:1.7.9.1-1~), python-dateutil 28 | Recommends: pristine-tar (>= 0.5), cowbuilder 29 | Suggests: python-notify, unzip 30 | Description: Suite to help with Debian packages in Git repositories 31 | This package contains the following tools: 32 | * git-import-{dsc,dscs}: import existing Debian source packages into a git 33 | repository 34 | * git-import-orig: import a new upstream version into the git repository 35 | * git-buildpackage: build a package out of a git repository, check for local 36 | modifications and tag appropriately 37 | * git-dch: generate Debian changelog entries from Git commit messages 38 | * gbp-{pull,clone}: clone and pull from remote repos 39 | * gbp-pq: manage debian/patches easily 40 | * gbp-create-remote-repo: create remote repositories 41 | """ 42 | 43 | 44 | def test_parse_control(): 45 | """ 46 | Parse a the control of debian package 47 | 48 | Methods tested: 49 | - L{gbp.deb.control.Control.__init__} 50 | 51 | Properties tested: 52 | - L{gbp.deb.control.Control.name} 53 | - L{gbp.deb.control.Control.section} 54 | - L{gbp.deb.control.Control.priority} 55 | 56 | >>> import gbp.deb.control 57 | >>> cl = gbp.deb.control.Control(cl_debian) 58 | >>> cl.name 59 | 'git-buildpackage' 60 | >>> cl.name == cl['Source'] 61 | True 62 | >>> cl.section 63 | 'vcs' 64 | >>> cl.section == cl['Section'] 65 | True 66 | >>> cl.priority 67 | 'optional' 68 | >>> cl.priority == cl['Priority'] 69 | True 70 | >>> cl['Standards-Version'] 71 | '3.9.3' 72 | >>> cl['Package'] 73 | 74 | """ 75 | 76 | 77 | def test_no_control_error(): 78 | """ 79 | Raise an error if no control file exist or is empty 80 | 81 | Methods tested: 82 | - L{gbp.deb.control.Control.__init__} 83 | 84 | >>> import gbp.deb.control 85 | >>> cl = gbp.deb.control.Control(filename="doesnotexist") 86 | Traceback (most recent call last): 87 | ... 88 | gbp.deb.control.NoControlError: Control file doesnotexist does not exist 89 | >>> cl = gbp.deb.control.Control("notparsable") 90 | Traceback (most recent call last): 91 | ... 92 | gbp.deb.control.ParseControlError: Empty or invalid control file or contents 93 | """ 94 | -------------------------------------------------------------------------------- /tests/doctests/test_GitModifier.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """ 4 | Test L{gbp.git.GitModifier} 5 | """ 6 | 7 | from .. import context # noqa: F401 8 | 9 | 10 | def test_author(): 11 | """ 12 | Methods tested: 13 | - L{gbp.git.GitModifier.get_author_env} 14 | - L{gbp.git.GitModifier.get_committer_env} 15 | - L{gbp.git.GitModifier.keys} 16 | 17 | >>> import gbp.git 18 | >>> modifier = gbp.git.GitModifier('foo', 'bar') 19 | >>> modifier.name 20 | 'foo' 21 | >>> modifier.email 22 | 'bar' 23 | >>> modifier.get_author_env()['GIT_AUTHOR_EMAIL'] 24 | 'bar' 25 | >>> modifier.get_author_env()['GIT_AUTHOR_NAME'] 26 | 'foo' 27 | >>> modifier.get_committer_env()['GIT_COMMITTER_NAME'] 28 | 'foo' 29 | >>> modifier.get_committer_env()['GIT_COMMITTER_EMAIL'] 30 | 'bar' 31 | >>> modifier._get_env('foo') 32 | Traceback (most recent call last): 33 | ... 34 | gbp.git.modifier.GitModifierError: Neither committer nor author 35 | >>> modifier['name'] 36 | 'foo' 37 | >>> modifier['email'] 38 | 'bar' 39 | >>> modifier['date'] 40 | """ 41 | 42 | 43 | def test_date(): 44 | """ 45 | Methods tested: 46 | - L{gbp.git.GitModifier.__init__} 47 | 48 | Properties tested: 49 | - L{gbp.git.GitModifier.date} 50 | - L{gbp.git.GitModifier.datetime} 51 | - L{gbp.git.GitModifier.tz_offset} 52 | 53 | >>> import gbp.git 54 | >>> import datetime 55 | >>> modifier = gbp.git.GitModifier('foo', 'bar', 1) 56 | >>> modifier.date 57 | '1 +0000' 58 | >>> modifier.date = '1 +0400' 59 | >>> modifier.date 60 | '1 +0400' 61 | >>> modifier['date'] 62 | '1 +0400' 63 | >>> modifier.datetime # doctest: +ELLIPSIS 64 | datetime.datetime(1970, 1, 1, 4, 0, 1, tzinfo=) 65 | >>> modifier.date = datetime.datetime(1970, 1, 1, 0, 0, 1) 66 | >>> modifier.date 67 | '1 +0000' 68 | >>> modifier.datetime # doctest: +ELLIPSIS 69 | datetime.datetime(1970, 1, 1, 0, 0, 1, tzinfo=) 70 | >>> modifier.tz_offset 71 | '+0000' 72 | """ 73 | 74 | 75 | def test_dict(): 76 | """ 77 | Test C{dict} interface 78 | >>> import gbp.git 79 | >>> modifier = gbp.git.GitModifier('foo', 'bar', 1) 80 | >>> sorted(modifier.keys()) 81 | ['date', 'email', 'name'] 82 | >>> sorted(modifier.items()) 83 | [('date', '1 +0000'), ('email', 'bar'), ('name', 'foo')] 84 | >>> modifier.get('name') 85 | 'foo' 86 | >>> modifier.get('doesnotexist') 87 | """ 88 | -------------------------------------------------------------------------------- /tests/doctests/test_GitVfs.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | """ 4 | Test L{gbp.git.GitVfs} 5 | """ 6 | 7 | import os 8 | import gbp.log 9 | 10 | from .. import context # noqa: F401 11 | 12 | gbp.log.setup(color=False, verbose=True) 13 | 14 | 15 | def setup_repo(): 16 | repo_dir = context.new_tmpdir(__name__) 17 | repo = gbp.git.GitRepository.create(str(repo_dir)) 18 | content = b'al pha\na\nb\nc' 19 | with open(os.path.join(repo.path, 'foo.txt'), 'w') as f: 20 | f.write(content.decode()) 21 | repo.add_files(repo.path, force=True) 22 | repo.commit_all(msg="foo") 23 | return (repo, content) 24 | 25 | 26 | def test_read(): 27 | """ 28 | Create a repository 29 | 30 | Methods tested: 31 | - L{gbp.git.GitVfs.open} 32 | - L{gbp.git.GitVfs._File.readline} 33 | - L{gbp.git.GitVfs._File.readlines} 34 | - L{gbp.git.GitVfs._File.read} 35 | - L{gbp.git.GitVfs._File.close} 36 | 37 | >>> import gbp.git.vfs 38 | >>> (repo, content) = setup_repo() 39 | >>> vfs = gbp.git.vfs.GitVfs(repo, 'HEAD') 40 | >>> gf = vfs.open('foo.txt') 41 | >>> gf.readline() 42 | 'al pha\\n' 43 | >>> gf.readline() 44 | 'a\\n' 45 | >>> gf.readlines() 46 | ['b\\n', 'c'] 47 | >>> gf.readlines() 48 | [] 49 | >>> gf.readline() 50 | '' 51 | >>> gf.readline() 52 | '' 53 | >>> gf.close() 54 | >>> gbp.git.vfs.GitVfs(repo, 'HEAD').open('foo.txt').read() == content.decode() 55 | True 56 | >>> gf = vfs.open('doesnotexist') # doctest:+IGNORE_EXCEPTION_DETAIL 57 | Traceback (most recent call last): 58 | ... 59 | OSError: can't get HEAD:doesnotexist: fatal: Path 'doesnotexist' does not exist in 'HEAD' 60 | >>> context.teardown() 61 | """ 62 | 63 | 64 | def test_binary_read(): 65 | """ 66 | Create a repository 67 | 68 | Methods tested: 69 | - L{gbp.git.GitVfs.open} 70 | - L{gbp.git.GitVfs._File.readline} 71 | - L{gbp.git.GitVfs._File.readlines} 72 | - L{gbp.git.GitVfs._File.read} 73 | - L{gbp.git.GitVfs._File.close} 74 | 75 | >>> import gbp.git.vfs 76 | >>> (repo, content) = setup_repo() 77 | >>> vfs = gbp.git.vfs.GitVfs(repo, 'HEAD') 78 | >>> gf = vfs.open('foo.txt', 'rb') 79 | >>> gf.readline() 80 | b'al pha\\n' 81 | >>> gf.readline() 82 | b'a\\n' 83 | >>> gf.readlines() 84 | [b'b\\n', b'c'] 85 | >>> gf.readlines() 86 | [] 87 | >>> gf.readline() 88 | b'' 89 | >>> gf.readline() 90 | b'' 91 | >>> gf.close() 92 | >>> gbp.git.vfs.GitVfs(repo, 'HEAD').open('foo.txt', 'rb').read() == content 93 | True 94 | >>> gf = vfs.open('doesnotexist') # doctest:+IGNORE_EXCEPTION_DETAIL 95 | Traceback (most recent call last): 96 | ... 97 | OSError: can't get HEAD:doesnotexist: fatal: Path 'doesnotexist' does not exist in 'HEAD' 98 | >>> context.teardown() 99 | """ 100 | 101 | 102 | def test_content_manager(): 103 | """ 104 | Create a repository 105 | 106 | Methods tested: 107 | - L{gbp.git.GitVfs.open} 108 | 109 | >>> import gbp.git.vfs 110 | >>> (repo, content) = setup_repo() 111 | >>> vfs = gbp.git.vfs.GitVfs(repo, 'HEAD') 112 | >>> with vfs.open('foo.txt') as gf: 113 | ... data = gf.readlines() 114 | >>> data 115 | ['al pha\\n', 'a\\n', 'b\\n', 'c'] 116 | """ 117 | -------------------------------------------------------------------------------- /tests/test_RollbackDebianGitRepository.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | """Test L{gbp.deb.rollbackgit}""" 3 | 4 | import os 5 | 6 | from . testutils import DebianGitTestRepo 7 | from gbp.deb.rollbackgit import RollbackDebianGitRepository 8 | from gbp.git.repository import GitRepositoryError 9 | 10 | 11 | class TestRollbackGitRepository(DebianGitTestRepo): 12 | 13 | def setUp(self): 14 | DebianGitTestRepo.setUp(self, RollbackDebianGitRepository) 15 | 16 | def test_empty_rollback(self): 17 | self.repo.rollback() 18 | self.assertEqual(self.repo.rollback_errors, []) 19 | 20 | def test_rrr_tag(self): 21 | self.repo.rrr_tag('doesnotexist') 22 | self.assertEqual(self.repo.rollbacks, [('doesnotexist', 'tag', 'delete', None)]) 23 | self.repo.rollback() 24 | self.assertEqual(self.repo.rollback_errors, []) 25 | 26 | def test_rrr_branch(self): 27 | self.repo.rrr_branch('doesnotexist', 'delete') 28 | self.assertEqual(self.repo.rollbacks, [('doesnotexist', 'branch', 'delete', None)]) 29 | self.repo.rollback() 30 | self.assertEqual(self.repo.rollback_errors, []) 31 | 32 | def test_rrr_merge(self): 33 | self.repo.rrr_merge('HEAD') 34 | self.assertEqual(self.repo.rollbacks, [('HEAD', 'commit', 'abortmerge', None)]) 35 | self.repo.rollback() 36 | self.assertEqual(self.repo.rollback_errors, []) 37 | 38 | def test_rrr_merge_abort(self): 39 | self.repo.rrr_merge('HEAD') 40 | self.assertEqual(self.repo.rollbacks, [('HEAD', 'commit', 'abortmerge', None)]) 41 | # Test that we abort the merge in case MERGE_HEAD exists 42 | with open(os.path.join(self.repo.git_dir, 'MERGE_HEAD'), 'w'): 43 | pass 44 | self.assertTrue(self.repo.is_in_merge()) 45 | self.repo.rollback() 46 | self.assertFalse(self.repo.is_in_merge()) 47 | self.assertEqual(self.repo.rollback_errors, []) 48 | 49 | def test_rrr_unknown_action(self): 50 | with self.assertRaisesRegex(GitRepositoryError, "Unknown action 'unknown' for tag 'doesnotmatter'"): 51 | self.repo.rrr('doesnotmatter', 'unknown', 'tag') 52 | -------------------------------------------------------------------------------- /tests/testutils/capture.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | import sys 4 | from contextlib import contextmanager 5 | from io import StringIO 6 | 7 | 8 | class _StderrCapture(StringIO): 9 | def save(self): 10 | self.safed = sys.stderr 11 | sys.stderr = self 12 | 13 | def restore(self): 14 | if self.safed is not None: 15 | sys.stderr = self.safed 16 | self.safed = None 17 | 18 | def output(self): 19 | self.seek(0) 20 | return self.read() 21 | 22 | 23 | class _StdoutCapture(StringIO): 24 | def save(self): 25 | self.safed = sys.stdout 26 | sys.stdout = self 27 | 28 | def restore(self): 29 | if self.safed is not None: 30 | sys.stdout = self.safed 31 | self.safed = None 32 | 33 | def output(self): 34 | self.seek(0) 35 | return self.read() 36 | 37 | 38 | @contextmanager 39 | def capture_stderr(): 40 | """Capture an output and return its content""" 41 | c = _StderrCapture() 42 | c.save() 43 | yield c 44 | c.restore() 45 | 46 | 47 | @contextmanager 48 | def capture_stdout(): 49 | """Capture an output and return its content""" 50 | c = _StdoutCapture() 51 | c.save() 52 | yield c 53 | c.restore() 54 | -------------------------------------------------------------------------------- /tests/testutils/data.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | # 3 | # (C) 2016 Guido Günther 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, please see 16 | # 17 | 18 | from functools import wraps 19 | 20 | import unittest 21 | 22 | 23 | class TestCaseWithData(unittest.TestCase): 24 | @staticmethod 25 | def feed(data): 26 | def wrapper(fn): 27 | @wraps(fn) 28 | def feed_item(self, *args): 29 | for d in data: 30 | try: 31 | fn(self, *((d,) + args)) 32 | except self.failureException as e: 33 | raise self.failureException(e.message + " with data %s" % repr(d)) 34 | return feed_item 35 | return wrapper 36 | -------------------------------------------------------------------------------- /tests/testutils/debiangittestrepo.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | from .. import context 4 | 5 | import os 6 | import unittest 7 | 8 | import gbp.deb.git 9 | 10 | 11 | class DebianGitTestRepo(unittest.TestCase): 12 | """Scratch repo for a single unit test""" 13 | 14 | def setUp(self, repo_cls=None): 15 | name = 'test_repo' 16 | self.tmpdir = context.new_tmpdir(__name__) 17 | 18 | if repo_cls is None: 19 | repo_cls = gbp.deb.git.DebianGitRepository 20 | 21 | repodir = self.tmpdir.join(name) 22 | self.repodir = os.path.join(str(self.tmpdir), name) 23 | self.repo = repo_cls.create(repodir) 24 | 25 | def tearDown(self): 26 | context.teardown() 27 | 28 | def add_file(self, name, content=None, msg=None, mode=None): 29 | """ 30 | Add a single file with name I{name} and content I{content}. If 31 | I{content} is C{none} the content of the file is undefined. 32 | 33 | @param name: the file's path relative to the git repo 34 | @type name: C{str} 35 | @param content: the file's content 36 | @type content: C{str} 37 | """ 38 | path = os.path.join(self.repo.path, name) 39 | 40 | d = os.path.dirname(path) 41 | if not os.path.exists(d): 42 | os.makedirs(d) 43 | 44 | with open(path, mode or 'w+') as f: 45 | content is None or f.write(content) 46 | self.repo.add_files(name, force=True) 47 | self.repo.commit_files(path, msg or "added %s" % name) 48 | -------------------------------------------------------------------------------- /tests/testutils/popen.py: -------------------------------------------------------------------------------- 1 | # vim: set fileencoding=utf-8 : 2 | 3 | import functools 4 | from unittest import mock 5 | 6 | 7 | def patch_popen(stdout=b'', stderr=b'', returncode=1): 8 | """Decorator to easily set the return value of popen.communicate()""" 9 | def patch_popen_decorator(func): 10 | @functools.wraps(func) 11 | def wrap(self): 12 | with mock.patch('subprocess.Popen') as create_mock: 13 | popen_mock = mock.Mock(**{'returncode': returncode, 14 | 'communicate.return_value': (stdout, stderr)}) 15 | create_mock.return_value = popen_mock 16 | return func(self, create_mock) 17 | return wrap 18 | return patch_popen_decorator 19 | --------------------------------------------------------------------------------