Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: "actions/checkout@v3"
- uses: "actions/setup-python@v4"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ docs/_build/

# PyBuilder
target/

.venv/
9 changes: 5 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
rev: v5.0.0
hooks:
- id: check-toml
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/PyCQA/flake8
rev: "3.9.2"
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
hooks:
- id: flake8
- id: ruff
args: [--fix]
70 changes: 70 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ Create a ``repos.yaml`` or ``repos.yml`` file:
fetch_all:
- oca

./gitlab-repo-example:
remotes:
gitlab_1: https://giltab.com/sample-org/sample-repo.git
gitlab_2: https://giltab.com/another-sample-org/sample-repo-fork.git
merges:
- gitlab_1 main
- gitlab_2 merge-requests/123/head
target: gitlab_1

# FYI: Bitbucket doesn't support fetching PR's
./bitbucket-repo-example:
remotes:
bitbucket_1: https://bitbucket.org/sample-org/sample-repo.git
bitbucket_2: https://bitbucker.org/another-sample-org/sample-repo-fork.git
merges:
- bitbucket_1 main
- bitbucket_2 dev
target: bitbucket_1



Environment variables inside of this file will be expanded if the proper option is selected.

All the ``merges`` are combined into a single branch. By default this branch is called ``_git_aggregated`` but another name may be given in the ``target`` section.
Expand Down Expand Up @@ -107,6 +128,38 @@ the ``dict`` alternate construction. If you need to disable a default in
ref: refs/pull/14859/head
target: acsone 9.0

./gitlab-repo-example:
defaults:
depth: 20
remotes:
gitlab_1: https://giltab.com/sample-org/sample-repo.git
gitlab_2: https://giltab.com/another-sample-org/sample-repo-fork.git
merges:
-
remote: gitlab_1
ref: main
depth: 20
-
remote: gitlab_2
ref: merge-requests/123/head
target: gitlab_1

# FYI: Bitbucket doesn't support fetching PR's
./bitbucket-repo-example:
remotes:
bitbucket_1: https://bitbucket.org/sample-org/sample-repo.git
bitbucket_2: https://bitbucker.org/another-sample-org/sample-repo-fork.git
merges:
-
remote: bitbucket_1
ref: main
depth: 3
-
remote: bitbucket_2
ref: dev
target: bitbucket_1


Remember that you need to fetch at least the common ancestor of all merges for
it to succeed.

Expand Down Expand Up @@ -224,6 +277,23 @@ To work around API limitation, you must first generate a
Changes
=======

4.1 (2025-03-25)
----------------

* Update README for other forges than GitHub (`#88 <https://github.com/acsone/git-aggregator/pull/88>`_)
* Internal API change (`#91 <https://github.com/acsone/git-aggregator/pull/91>`_)
* Drop support for unsupported Python versions (`#92 <https://github.com/acsone/git-aggregator/pull/92>`_)

4.0.2 (2024-10-23)
------------------

* target_dir may be an empty directory (`#83 <https://github.com/acsone/git-aggregator/pull/83>`_)

4.0.1 (2024-06-04)
------------------

* fix: git remote: change url instead of rm / add (`#81 <https://github.com/acsone/git-aggregator/pull/81>`_`)

4.0 (2023-07-22)
----------------

Expand Down
1 change: 0 additions & 1 deletion git_aggregator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
1 change: 0 additions & 1 deletion git_aggregator/_compat.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
import sys
Expand Down
20 changes: 13 additions & 7 deletions git_aggregator/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)

Expand All @@ -8,10 +7,9 @@

import yaml

from .exception import ConfigException
from ._compat import string_types
from .repo import Repo, ishex

from .exception import ConfigException

log = logging.getLogger(__name__)

Expand All @@ -37,6 +35,8 @@ def get_repos(config, force=False, skip_merge_check=False):
'apply_patch': repo_data.get('apply_patch', False),
'skip_repo_init': repo_data.get('skip_repo_init', False),
}
if 'retry' in repo_data:
repo_dict['retry'] = repo_data['retry']
remote_names = set()
if 'remotes' in repo_data:
repo_dict['remotes'] = []
Expand All @@ -57,7 +57,10 @@ def get_repos(config, force=False, skip_merge_check=False):
'%s: You should at least define one remote.' % directory)
else:
try:
tmp_repo = Repo(repo_dict['cwd'], [], [], None)
tmp_repo = Repo(
repo_dict['cwd'], [], [], None,
retry={"max_retries": 0},
)
remotes = tmp_repo._get_remotes()
repo_dict['remotes'] = []
for remote_name, url in remotes.items():
Expand All @@ -73,7 +76,10 @@ def get_repos(config, force=False, skip_merge_check=False):
merge_data = repo_data.get('merges') or []
tmp_repo = None
if not skip_merge_check:
tmp_repo = Repo(repo_dict['cwd'], [], [], None)
tmp_repo = Repo(
repo_dict['cwd'], [], [], None,
retry={"max_retries": 0},
)
if os.path.exists(tmp_repo.cwd):
# Set remotes
for remote in repo_dict['remotes']:
Expand Down Expand Up @@ -207,11 +213,11 @@ def load_config(
key, value = line.split('=')
environment.update({key.strip(): value.strip()})
environment.update(os.environ)
with open(config, 'r') as file_handler:
with open(config) as file_handler:
config = Template(file_handler.read())
config = config.substitute(environment)
else:
config = open(config, 'r').read()
config = open(config).read()

conf = yaml.load(config, Loader=yaml.SafeLoader)

Expand Down
1 change: 0 additions & 1 deletion git_aggregator/exception.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)

Expand Down
1 change: 0 additions & 1 deletion git_aggregator/log.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)

Expand Down
22 changes: 11 additions & 11 deletions git_aggregator/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015-2019 ACSONE SA/NV
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)

Expand All @@ -7,22 +6,24 @@
import sys
import threading
import traceback

try:
from Queue import Queue, Empty as EmptyQueue
from Queue import Empty as EmptyQueue
from Queue import Queue
except ImportError:
from queue import Queue, Empty as EmptyQueue
from queue import Empty as EmptyQueue
from queue import Queue

import argparse
import fnmatch

import argcomplete
import colorama
import fnmatch

from .utils import ThreadNameKeeper
from .log import DebugLogFormatter
from .log import LogFormatter
from .config import load_config
from .log import DebugLogFormatter, LogFormatter
from .repo import Repo

from .utils import ThreadNameKeeper

logger = logging.getLogger(__name__)

Expand All @@ -31,8 +32,7 @@

def _log_level_string_to_int(log_level_string):
if log_level_string not in _LOG_LEVEL_STRINGS:
message = 'invalid choice: {0} (choose from {1})'.format(
log_level_string, _LOG_LEVEL_STRINGS)
message = f'invalid choice: {log_level_string} (choose from {_LOG_LEVEL_STRINGS})'
raise argparse.ArgumentTypeError(message)

log_level_int = getattr(logging, log_level_string, logging.INFO)
Expand Down Expand Up @@ -99,7 +99,7 @@ def get_parser():
dest='log_level',
type=_log_level_string_to_int,
nargs='?',
help='Set the logging output level. {0}'.format(_LOG_LEVEL_STRINGS))
help=f'Set the logging output level. {_LOG_LEVEL_STRINGS}')

main_parser.add_argument(
'-e', '--expand-env',
Expand Down
Loading
Loading