Skip to content

Commit 3fc5e29

Browse files
authored
feat(mr,diff): #13 - add diff and get_latest_mr_state
1 parent 126311a commit 3fc5e29

File tree

7 files changed

+159
-4
lines changed

7 files changed

+159
-4
lines changed

.dockerignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Specific files/folder
2+
.cache
3+
.coverage
4+
.coveragerc
5+
.dockerignore
6+
.git
7+
.gitignore
8+
.gitlab-ci.yml
9+
.noserc
10+
.venv/
11+
.idea
12+
.vscode
13+
htmlcov
14+
sonar-project.properties
15+
**/tests/**
16+
*.egg-info
17+
.flake8
18+
docs/
19+
devops/
20+
tmp/
21+
.gitlab/
22+
.releaserc.json$
23+
README.rst
24+
sonar-project.properties
25+
pylama.ini
26+
openapi.yml
27+
cov.xml
28+
commitlint.config.js
29+
codespellrc
30+
CHANGELOG.md
31+
celerybeat-schedule.db
32+
.pre-commit-config.yaml
33+
.gitlab-ci.yml
34+
.coverage
35+
public
36+
*/__pycache__/
37+
# Ignore all markdown file
38+
*.md
39+
# Ignore all *.pyc files in all folders, including build root
40+
**/*.pyc

gitflow_toolbox/check_branch_exists.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ def check_branch_exists(ctx: click.Context, remote: bool, branch: str):
1616
Args:
1717
remote (bool): whether to check on the current gitlab or remote gitlab (True=remote)
1818
branch (str): branch name
19+
20+
Returns:
21+
bool: True if branch exists (exit code 0), False otherwise (exit code 1)
1922
"""
2023
click.echo(f"Checking if {branch} branch exists...")
2124
project = RemoteGitlab().project if remote else CurrentGitlab().project

gitflow_toolbox/check_mr_exists.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ def check_mr_exists(ctx: click.Context, remote: bool, source_branch: str, target
1919
remote (bool): whether to check on the current gitlab or remote gitlab (True=remote)
2020
source_branch (str): branch to create
2121
remote_target_branch (str): branch reference to create branch from
22+
23+
Returns:
24+
bool: True if a MR exists (exit code 0), False otherwise (exit code 1)
2225
"""
2326
click.echo(f"Checking if an opened merge request from {source_branch} to {target_branch} exists...")
2427
project = RemoteGitlab().project if remote else CurrentGitlab().project

gitflow_toolbox/diff.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import os
2+
import shutil
3+
import uuid
4+
5+
import click
6+
import git
7+
8+
from gitflow_toolbox.common.gitlab import CurrentGitlab, RemoteGitlab
9+
from gitflow_toolbox.common.is_main_call import is_main_call
10+
11+
12+
@click.command()
13+
@click.option("--from-gitlab", type=click.Choice(["current", "remote"], case_sensitive=False))
14+
@click.argument("source_branch", type=str)
15+
@click.option("--to-gitlab", type=click.Choice(["current", "remote"], case_sensitive=False))
16+
@click.argument("target_branch", type=str)
17+
@click.pass_context
18+
def diff(
19+
ctx: click.Context,
20+
from_gitlab: tuple[str],
21+
source_branch: str,
22+
to_gitlab: tuple[str],
23+
target_branch: str,
24+
):
25+
"""Returns the 'git diff' between two branches
26+
27+
Args:
28+
from_gitlab (str): source gitlab [current/remote]
29+
source_branch (str): source branch
30+
to_gitlab (str): destination gitlab [current/remote]
31+
target_branch (str): destination branch
32+
33+
Returns:
34+
str: the 'git diff' between two branches, or an empty string (line return) if no diff
35+
"""
36+
37+
gitlab_from = CurrentGitlab() if from_gitlab == "current" else RemoteGitlab()
38+
gitlab_to = CurrentGitlab() if to_gitlab == "current" else RemoteGitlab()
39+
40+
project_from_clone_dir = os.path.join("/tmp", f"gf_{uuid.uuid4()}")
41+
42+
try:
43+
# Clone
44+
repo_from = git.Repo.clone_from(
45+
gitlab_from.project_authenticated_url, project_from_clone_dir, branch=source_branch
46+
)
47+
# Add remote
48+
repo_from.create_remote("target", gitlab_to.project_authenticated_url)
49+
# Diff
50+
repo_from.remotes.target.fetch(target_branch)
51+
diff_output = str(repo_from.git.diff(f"target/{target_branch}"))
52+
if diff_output and is_main_call(ctx):
53+
click.echo(diff_output)
54+
return diff_output
55+
finally:
56+
# Clean
57+
if os.path.isdir(project_from_clone_dir):
58+
shutil.rmtree(project_from_clone_dir)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import click
2+
3+
from gitflow_toolbox.common.gitlab import CurrentGitlab, RemoteGitlab
4+
from gitflow_toolbox.common.is_main_call import is_main_call
5+
6+
7+
@click.command()
8+
@click.option("--remote/--current", default=False)
9+
@click.argument("source_branch", type=str)
10+
@click.argument("target_branch", type=str)
11+
@click.argument("labels", type=str, nargs=-1)
12+
@click.pass_context
13+
def get_latest_mr_state(ctx: click.Context, remote: bool, source_branch: str, target_branch: str, labels: tuple[str]):
14+
"""Returns the state of the latest MR from/to branch
15+
16+
Args:
17+
remote (bool): whether to check on the current gitlab or remote gitlab (True=remote)
18+
source_branch (str): branch to create
19+
remote_target_branch (str): branch reference to create branch from
20+
labels (tuple[str]): filter by labels
21+
22+
Returns:
23+
str: state of the latest MR (opened/closed/merged/locked) or 'no-mr' if nothing was found
24+
"""
25+
project = RemoteGitlab().project if remote else CurrentGitlab().project
26+
mrs = project.mergerequests.list(
27+
source_branch=source_branch, target_branch=target_branch, order_by="created_at", labels=list(labels)
28+
)
29+
if len(mrs) == 0:
30+
if is_main_call(ctx):
31+
click.echo("no-mr")
32+
return "no-mr"
33+
if is_main_call(ctx):
34+
click.echo(mrs[0].state)
35+
return mrs[0].state

gitflow_toolbox/push.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import shutil
3+
import sys
34
import uuid
45

56
import click
@@ -24,28 +25,41 @@ def push(
2425
target_branch: str,
2526
force: bool,
2627
):
28+
"""Push commits from a branch to another branch
29+
30+
Args:
31+
from_gitlab (str): source gitlab [current/remote]
32+
source_branch (str): source branch
33+
to_gitlab (str): destination gitlab [current/remote]
34+
target_branch (str): destination branch
35+
force (bool): whether to force push (default: False)
36+
"""
2737

2838
gitlab_from = CurrentGitlab() if from_gitlab == "current" else RemoteGitlab()
2939
gitlab_to = CurrentGitlab() if to_gitlab == "current" else RemoteGitlab()
3040

3141
project_from_http_url = ctx.invoke(get_project_http_url, remote=(from_gitlab == "remote"))
3242
project_from_clone_dir = os.path.join("/tmp", f"gf_{uuid.uuid4()}")
3343

34-
# Clone
3544
click.echo(f"Cloning {project_from_http_url} into {project_from_clone_dir}")
36-
3745
try:
46+
# Clone
3847
repo_from = git.Repo.clone_from(
3948
gitlab_from.project_authenticated_url, project_from_clone_dir, branch=source_branch
4049
)
41-
# Check if directory exists
4250
# Add remote
4351
project_to_http_url = ctx.invoke(get_project_http_url, remote=(to_gitlab == "remote"))
4452
click.echo(f"Adding remote to {project_to_http_url}")
4553
repo_from.create_remote("target", gitlab_to.project_authenticated_url)
4654
# Push
55+
repo_from.remotes.target.fetch(target_branch)
4756
click.echo(f"Pushing {from_gitlab} {source_branch} into {to_gitlab} {target_branch} (force={force})")
48-
repo_from.remotes.target.push(refspec=f"{source_branch}:{target_branch}", force=force)
57+
changes = repo_from.remotes.target.push(refspec=f"{source_branch}:{target_branch}", force=force)
58+
for change in changes:
59+
click.echo(change.summary)
60+
if "rejected" in change.summary:
61+
click.echo(f"❌ Couldn't push changes to {to_gitlab} {target_branch}")
62+
sys.exit(1)
4963
click.echo(f"✨ Successfully pushed {from_gitlab} {source_branch} into {to_gitlab} {target_branch}")
5064

5165
finally:

main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from gitflow_toolbox.check_branch_exists import check_branch_exists
55
from gitflow_toolbox.check_mr_exists import check_mr_exists
6+
from gitflow_toolbox.diff import diff
67
from gitflow_toolbox.ensure_branch import ensure_branch
78
from gitflow_toolbox.ensure_mr import ensure_mr
89
from gitflow_toolbox.get_project_http_url import get_project_http_url
@@ -24,6 +25,7 @@ def cli():
2425
cli.add_command(get_project_ssh_url)
2526
cli.add_command(get_project_http_url)
2627
cli.add_command(push)
28+
cli.add_command(diff)
2729

2830
if __name__ == "__main__":
2931
cli()

0 commit comments

Comments
 (0)