Merge pull request !2927 from rhodecode-enterprise-ce multi-branch

Changes from branch: Multi branch
This commit is contained in:
Andrii Verbytskyi 2025-12-23 10:59:24 +00:00
commit 515fc40de7
54 changed files with 472 additions and 241 deletions

View file

@ -4,7 +4,7 @@ furo==2023.9.10
sphinx-press-theme==0.8.0
sphinx-rtd-theme==1.3.0
pygments==2.18.0
pygments==2.19.2
docutils<0.19
markupsafe==2.1.3

View file

@ -4,12 +4,12 @@ alembic==1.13.1
mako==1.3.10
MarkupSafe==3.0.3
sqlalchemy==1.4.54
greenlet==3.2.4
greenlet==3.3.0
typing_extensions==4.15.0
async-timeout==4.0.3
babel==2.12.1
beaker==1.13.0
celery==5.5.3
celery==5.6.0
billiard==4.2.3
click==8.1.8
click-didyoumean==0.3.1
@ -20,7 +20,7 @@ celery==5.5.3
click==8.1.8
prompt_toolkit==3.0.48
wcwidth==0.2.13
kombu==5.5.4
kombu==5.6.1
amqp==5.3.1
vine==5.1.0
tzdata==2025.2
@ -31,8 +31,8 @@ celery==5.5.3
vine==5.1.0
channelstream==0.7.1
gevent==25.9.1
greenlet==3.2.4
zope.event==6.0.0
greenlet==3.3.0
zope.event==6.1.0
zope.interface==8.1.1
itsdangerous==1.1.0
marshmallow==2.18.0
@ -80,8 +80,8 @@ deform==2.0.15
peppercorn==0.6
translationstring==1.4
zope.deprecation==6.0.0
docutils==0.19
dogpile.cache==1.3.4
docutils==0.22.4
dogpile.cache==1.5.0
decorator==5.1.1
stevedore==5.1.0
pbr==5.11.1
@ -91,8 +91,8 @@ fsspec==2025.10.0
gunicorn==23.0.0
packaging==24.1
gevent==25.9.1
greenlet==3.2.4
zope.event==6.0.0
greenlet==3.3.0
zope.event==6.1.0
zope.interface==8.1.1
ipython==8.26.0
decorator==5.1.1
@ -104,7 +104,7 @@ ipython==8.26.0
ptyprocess==0.7.0
prompt_toolkit==3.0.48
wcwidth==0.2.13
pygments==2.18.0
pygments==2.19.2
stack-data==0.6.3
asttokens==2.4.1
six==1.17.0
@ -138,7 +138,7 @@ nbconvert==7.7.3
python-dateutil==2.9.0.post0
six==1.17.0
pyzmq==26.2.0
tornado==6.4.2
tornado==6.5.3
traitlets==5.14.3
jupyter_core==5.3.1
platformdirs==3.10.0
@ -163,11 +163,11 @@ nbconvert==7.7.3
traitlets==5.14.3
traitlets==5.14.3
pandocfilters==1.5.0
pygments==2.18.0
pygments==2.19.2
tinycss2==1.2.1
webencodings==0.5.1
traitlets==5.14.3
orjson==3.10.14
orjson==3.11.5
paste==3.10.1
premailer==3.10.0
cachetools==5.3.3
@ -180,13 +180,13 @@ premailer==3.10.0
idna==3.11
urllib3==2.5.0
psutil==5.9.8
psycopg2==2.9.10
psycopg2==2.9.11
py-bcrypt==0.4
pycmarkgfm==1.2.0
cffi==1.17.1
pycparser==2.22
cffi==2.0.0
pycparser==2.23
pycryptodome==3.21.0
pycurl==7.45.4
pycurl==7.45.7
pymysql==1.1.1
pyotp==2.8.0
pyparsing==3.1.1
@ -284,12 +284,12 @@ s3fs==2025.10.0
simplejson==3.19.2
sshpubkeys==3.3.1
cryptography==44.0.1
cffi==1.17.1
pycparser==2.22
ecdsa==0.19.0
cffi==2.0.0
pycparser==2.23
ecdsa==0.19.1
six==1.17.0
sqlalchemy==1.4.54
greenlet==3.2.4
greenlet==3.3.0
typing_extensions==4.15.0
supervisor==4.2.5
tzlocal==4.3
@ -297,7 +297,7 @@ tzlocal==4.3
tzdata==2025.2
tempita==0.5.2
unidecode==1.3.8
urlobject==2.4.3
urlobject==3.0.0
waitress==3.0.2
webhelpers2==2.1
MarkupSafe==3.0.3

View file

@ -41,8 +41,7 @@ class TestGetRepoChangeset(object):
if details == "full":
assert result["refs"]["bookmarks"] == getattr(commit, "bookmarks", [])
branches = [commit.branch] if commit.branch else []
assert result["refs"]["branches"] == branches
assert result["refs"]["branches"] == commit.branches
assert result["refs"]["tags"] == commit.tags
@pytest.mark.parametrize("details", ["basic", "extended", "full"])

View file

@ -324,7 +324,7 @@ def get_repo_changeset(request, apiuser, repoid, revision, details=Optional("bas
raise JSONRPCError("ret_type must be one of %s" % (",".join(_changes_details_types)))
vcs_repo = repo.scm_instance()
pre_load = ["author", "branch", "date", "message", "parents", "status", "_commit"]
pre_load = ["author", "branches", "date", "message", "parents", "status", "_commit"]
try:
commit = repo.get_commit(commit_id=revision, pre_load=pre_load)
@ -383,7 +383,7 @@ def get_repo_changesets(request, apiuser, repoid, start_rev, limit, details=Opti
raise JSONRPCError("ret_type must be one of %s" % (",".join(_changes_details_types)))
limit = int(limit)
pre_load = ["author", "branch", "date", "message", "parents", "status", "_commit"]
pre_load = ["author", "branches", "date", "message", "parents", "status", "_commit"]
vcs_repo = repo.scm_instance()
# SVN needs a special case to distinguish its index and commit id
@ -408,7 +408,7 @@ def get_repo_changesets(request, apiuser, repoid, start_rev, limit, details=Opti
_cs_json["diff"] = build_commit_data(vcs_repo, commit, changes_details)
if changes_details == "full":
_cs_json["refs"] = {
"branches": [commit.branch],
"branches": commit.branches,
"bookmarks": getattr(commit, "bookmarks", []),
"tags": commit.tags,
}

View file

@ -444,7 +444,7 @@ class RepoAppView(BaseAppView):
def get_commit_preload_attrs(cls):
pre_load = [
"author",
"branch",
"branches",
"date",
"message",
"parents",

View file

@ -24,11 +24,10 @@ from rhodecode.apps._base import ADMIN_PREFIX
from rhodecode.lib.hash_utils import md5_safe
from rhodecode.model.db import RhodeCodeUi
from rhodecode.model.meta import Session
from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel
from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel, VcsSettingsModel
from rhodecode.tests import assert_session_flash
from rhodecode.tests.routes import route_path
UPDATE_DATA_QUALNAME = "rhodecode.model.update.UpdateModel.get_update_data"
@ -207,8 +206,8 @@ class TestAdminSettingsVcs(object):
assert "important_tags/v0.5" in repo.tags
def test_add_same_svn_value_twice_shows_an_error_message(self, form_defaults, csrf_token, settings_util):
settings_util.create_rhodecode_ui("vcs_svn_branch", "/test")
settings_util.create_rhodecode_ui("vcs_svn_tag", "/test")
settings_util.create_rhodecode_ui(VcsSettingsModel.SVN_BRANCH_SECTION, "/test")
settings_util.create_rhodecode_ui(VcsSettingsModel.SVN_TAG_SECTION, "/test")
response = self.app.post(
route_path("admin_settings_vcs_update"),
@ -227,8 +226,8 @@ class TestAdminSettingsVcs(object):
@pytest.mark.parametrize(
"section",
[
"vcs_svn_branch",
"vcs_svn_tag",
VcsSettingsModel.SVN_BRANCH_SECTION,
VcsSettingsModel.SVN_TAG_SECTION,
],
)
def test_delete_svn_patterns(self, section, csrf_token, settings_util):
@ -243,8 +242,8 @@ class TestAdminSettingsVcs(object):
@pytest.mark.parametrize(
"section",
[
"vcs_svn_branch",
"vcs_svn_tag",
VcsSettingsModel.SVN_BRANCH_SECTION,
VcsSettingsModel.SVN_TAG_SECTION,
],
)
def test_delete_svn_patterns_raises_404_when_no_xhr(self, section, csrf_token, settings_util):

View file

@ -66,6 +66,8 @@ class AdminSettingsView(BaseAppView):
c = self._get_local_tmpl_context()
c.labs_active = str2bool(rhodecode.CONFIG.get("labs_settings_active", "true"))
c.navlist = navigation_list(self.request)
c.svn_default_branches = RhodeCodeUi.SVN_BRANCHES_PATTERNS
c.svn_default_tags = RhodeCodeUi.SVN_TAGS_PATTERNS
return c
@classmethod
@ -127,6 +129,7 @@ class AdminSettingsView(BaseAppView):
c.svn_tag_patterns = model.get_global_svn_tag_patterns()
c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
defaults = self._form_defaults()
data = render("rhodecode:templates/admin/settings/settings.mako", self._get_template_context(c), self.request)

View file

@ -107,7 +107,7 @@ class HoverCardsRepoView(RepoAppView):
def hovercard_repo_commit(self):
c = self.load_default_context()
commit_id = self.request.matchdict["commit_id"]
pre_load = ["author", "branch", "date", "message"]
pre_load = ["author", "branches", "date", "message"]
try:
c.commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id, pre_load=pre_load)
except (CommitDoesNotExistError, EmptyRepositoryError):

View file

@ -29,7 +29,7 @@ from rhodecode.lib.ext_json import json
from rhodecode.lib.str_utils import safe_str
from rhodecode.lib.vcs import nodes
from rhodecode.lib.vcs.conf import settings
from rhodecode.model.db import Session, Repository
from rhodecode.model.db import Session, Repository, RhodeCodeUi
from rhodecode.tests import assert_session_flash
from rhodecode.tests.fixtures.rc_fixture import Fixture
@ -181,8 +181,9 @@ class TestFilesViews(object):
response.mustcontain(msgbox % (commit.message,))
assert_response = response.assert_response()
if commit.branch:
assert_response.element_contains(".tags.tags-main .branchtag", commit.branch)
if commit.branches:
for branch in commit.branches:
assert_response.element_contains(".tags.tags-main .branchtag", branch)
if commit.tags:
for tag in commit.tags:
assert_response.element_contains(".tags.tags-main .tagtag", tag)
@ -230,15 +231,32 @@ class TestFilesViews(object):
for author in expected_authors[backend.alias]:
response.mustcontain(author)
def test_file_source_history(self, backend, xhr_header):
def test_file_source_history(self, backend, xhr_header, settings_util):
# set svn branch defaults
for branch in RhodeCodeUi.SVN_BRANCHES_PATTERNS:
settings_util.create_repo_rhodecode_ui(backend, RhodeCodeUi.SVN_BRANCH_ID, branch)
for tag in RhodeCodeUi.SVN_TAGS_PATTERNS:
settings_util.create_repo_rhodecode_ui(backend, RhodeCodeUi.SVN_TAG_ID, tag)
Session().commit()
response = self.app.get(
route_path("repo_file_history", repo_name=backend.repo_name, commit_id="tip", f_path="vcs/nodes.py"),
extra_environ=xhr_header,
)
assert get_node_history(backend.alias) == json.loads(response.body)
def test_file_source_history_svn(self, backend_svn, xhr_header):
def test_file_source_history_svn(self, backend_svn, xhr_header, settings_util):
simple_repo = backend_svn["svn-simple-layout"]
# set svn branch defaults
for branch in RhodeCodeUi.SVN_BRANCHES_PATTERNS:
settings_util.create_repo_rhodecode_ui(simple_repo, RhodeCodeUi.SVN_BRANCH_ID, branch)
for tag in RhodeCodeUi.SVN_TAGS_PATTERNS:
settings_util.create_repo_rhodecode_ui(simple_repo, RhodeCodeUi.SVN_TAG_ID, tag)
Session().commit()
response = self.app.get(
route_path(
"repo_file_history", repo_name=simple_repo.repo_name, commit_id="tip", f_path="trunk/example.py"

View file

@ -124,7 +124,7 @@ class TestSummaryView(object):
"sh": {"count": 2, "desc": ["Bash"]},
"bat": {"count": 1, "desc": ["Batch"]},
"cfg": {"count": 1, "desc": ["Ini"]},
"html": {"count": 1, "desc": ["EvoqueHtml", "Html"]},
"html": {"count": 1, "desc": ["Html"]},
"ini": {"count": 1, "desc": ["Ini"]},
"js": {"count": 1, "desc": ["Javascript"]},
"makefile": {"count": 1, "desc": ["Makefile", "Makefile"]},
@ -136,7 +136,7 @@ class TestSummaryView(object):
"sh": {"count": 2, "desc": ["Bash"]},
"bat": {"count": 1, "desc": ["Batch"]},
"cfg": {"count": 1, "desc": ["Ini"]},
"html": {"count": 1, "desc": ["EvoqueHtml", "Html"]},
"html": {"count": 1, "desc": ["Html"]},
"ini": {"count": 1, "desc": ["Ini"]},
"js": {"count": 1, "desc": ["Javascript"]},
"makefile": {"count": 1, "desc": ["Makefile", "Makefile"]},
@ -144,7 +144,7 @@ class TestSummaryView(object):
"svn": {
"py": {"count": 75, "desc": ["Python"]},
"rst": {"count": 16, "desc": ["Rst"]},
"html": {"count": 11, "desc": ["EvoqueHtml", "Html"]},
"html": {"count": 11, "desc": ["Html"]},
"css": {"count": 2, "desc": ["Css"]},
"bat": {"count": 1, "desc": ["Batch"]},
"cfg": {"count": 1, "desc": ["Ini"]},

View file

@ -88,7 +88,7 @@ class RepoCommitsView(RepoAppView):
commit_range = commit_id_range.split("...")[:2]
try:
pre_load = ["author", "branch", "date", "message", "parents"]
pre_load = ["author", "branches", "date", "message", "parents"]
if self.rhodecode_vcs_repo.alias == "hg":
pre_load += ["hidden", "obsolete", "phase"]

View file

@ -192,7 +192,7 @@ class RepoCompareView(RepoAppView):
c.source_ref_type = source_ref_type
c.target_ref_type = target_ref_type
pre_load = ["author", "date", "message", "branch"]
pre_load = ["author", "date", "message", "branches"]
c.ancestor = None
try:

View file

@ -99,7 +99,7 @@ class RepoFeedView(RepoAppView):
return date
def _get_commits(self):
pre_load = ["author", "branch", "date", "message", "parents"]
pre_load = ["author", "branches", "date", "message", "parents"]
if self.rhodecode_vcs_repo.is_empty():
return []

View file

@ -289,7 +289,7 @@ class RepoFilesView(RepoAppView):
else:
commit = repo.get_commit(commit_id=commit_id)
if commit:
branch_name = commit.branch
branch_name = commit.last_branch
sha_commit_id = commit.raw_id
return branch_name, sha_commit_id, is_head
@ -715,9 +715,9 @@ class RepoFilesView(RepoAppView):
)
c.on_branch_head = is_head
branch = c.commit.branch if (c.commit.branch and "/" not in c.commit.branch) else None
branch = c.commit.last_branch if (c.commit.last_branch and "/" not in c.commit.last_branch) else None
c.branch_or_raw_id = branch or c.commit.raw_id
c.branch_name = c.commit.branch or h.short_id(c.commit.raw_id)
c.branch_name = c.commit.last_branch or h.short_id(c.commit.raw_id)
author = c.file_last_commit.author
c.authors = [[h.email(author), h.person(author, "username_or_name_or_email"), 1]]
@ -973,7 +973,7 @@ class RepoFilesView(RepoAppView):
# calculate history based on tip
tip = self.rhodecode_vcs_repo.get_commit()
if commits is None:
pre_load = ["author", "branch"]
pre_load = ["author", "branches"]
try:
commits = tip.get_path_history(safe_bytes(f_path), pre_load=pre_load)
except (NodeDoesNotExistError, CommitError):
@ -983,7 +983,7 @@ class RepoFilesView(RepoAppView):
history = []
commits_group = ([], _("Changesets"))
for commit in commits:
branch = " (%s)" % commit.branch if commit.branch else ""
branch = " (%s)" % commit.last_branch if commit.last_branch else ""
n_desc = f"r{commit.idx}:{commit.short_id}{branch}"
commits_group[0].append((commit.raw_id, n_desc, "sha"))
history.append(commits_group)
@ -1296,9 +1296,8 @@ class RepoFilesView(RepoAppView):
c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias, branch=self.db_repo.landing_ref_name)
if self.rhodecode_vcs_repo.is_empty():
# for empty repository we cannot check for current branch, we rely on
# c.commit.branch instead
_branch_name, _sha_commit_id, is_head = c.commit.branch, "", True
# for empty repository we cannot check for current branch, we rely on default landing ref
_branch_name, _sha_commit_id, is_head = self.db_repo.landing_ref_name, "", True
else:
_branch_name, _sha_commit_id, is_head = self._is_valid_head(
commit_id, self.rhodecode_vcs_repo, landing_ref=self.db_repo.landing_ref_name
@ -1338,9 +1337,8 @@ class RepoFilesView(RepoAppView):
default_redirect_url = h.route_path("repo_commit", repo_name=self.db_repo_name, commit_id="tip")
if self.rhodecode_vcs_repo.is_empty():
# for empty repository we cannot check for current branch, we rely on
# c.commit.branch instead
_branch_name, _sha_commit_id, is_head = c.commit.branch, "", True
# for empty repository we cannot check for current branch, we rely on default landing ref
_branch_name, _sha_commit_id, is_head = self.db_repo.landing_ref_name, "", True
else:
_branch_name, _sha_commit_id, is_head = self._is_valid_head(
commit_id, self.rhodecode_vcs_repo, landing_ref=self.db_repo.landing_ref_name
@ -1424,9 +1422,8 @@ class RepoFilesView(RepoAppView):
default_redirect_url = h.route_path("repo_commit", repo_name=self.db_repo_name, commit_id="tip")
if self.rhodecode_vcs_repo.is_empty():
# for empty repository we cannot check for current branch, we rely on
# c.commit.branch instead
_branch_name, _sha_commit_id, is_head = c.commit.branch, "", True
# for empty repository we cannot check for current branch, we rely on default landing ref
_branch_name, _sha_commit_id, is_head = self.db_repo.landing_ref_name, "", True
else:
_branch_name, _sha_commit_id, is_head = self._is_valid_head(
commit_id, self.rhodecode_vcs_repo, landing_ref=self.db_repo.landing_ref_name
@ -1529,9 +1526,8 @@ class RepoFilesView(RepoAppView):
default_redirect_url = h.route_path("repo_commit", repo_name=self.db_repo_name, commit_id="tip")
if self.rhodecode_vcs_repo.is_empty():
# for empty repository we cannot check for current branch, we rely on
# c.commit.branch instead
_branch_name, _sha_commit_id, is_head = c.commit.branch, "", True
# for empty repository we cannot check for current branch, we rely on default landing ref
_branch_name, _sha_commit_id, is_head = self.db_repo.landing_ref_name, "", True
else:
_branch_name, _sha_commit_id, is_head = self._is_valid_head(
commit_id, self.rhodecode_vcs_repo, landing_ref=self.db_repo.landing_ref_name

View file

@ -858,7 +858,7 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
missing_requirements = False
try:
pre_load = ["author", "date", "message", "branch", "parents"]
pre_load = ["author", "date", "message", "branches", "parents"]
pull_request_commits = pull_request_at_ver.revisions
log.debug("Loading %s commits from %s", len(pull_request_commits), commits_source_repo)

View file

@ -29,6 +29,7 @@ from rhodecode.apps._base import RepoAppView
from rhodecode.apps.svn_support import config_keys
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired
from rhodecode.model.db import RhodeCodeUi
from rhodecode.model.forms import RepoVcsSettingsForm
from rhodecode.model.meta import Session
from rhodecode.model.settings import VcsSettingsModel, SettingNotFound
@ -39,6 +40,8 @@ log = logging.getLogger(__name__)
class RepoSettingsVcsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
c.svn_default_branches = RhodeCodeUi.SVN_BRANCHES_PATTERNS
c.svn_default_tags = RhodeCodeUi.SVN_TAGS_PATTERNS
return c
def _vcs_form_defaults(self, repo_name):

View file

@ -260,11 +260,11 @@ class TestSubversionServer(object):
"first_resp, expected_match",
[
(
b"( 2 ( edit-pipeline svndiff1 accepts-svndiff2 absent-entries depth mergeinfo log-revprops ) 44:svn+ssh://rc@code.example.com/TestRepo/trunk 34:SVN/1.14.5 (x64-microsoft-windows) ( 24:TortoiseSVN-1.14.9.29743 ) )",
b"( 2 ( edit-pipeline svndiff1 accepts-svndiff2 absent-entries depth mergeinfo log-revprops ) 44:svn+ssh://rc@code.example.com/TestRepo/trunk 34:SVN/1.14.5 (x64-microsoft-windows) ( 24:TortoiseSVN-1.14.9.29743 ) ) ",
None,
),
(
b"( 2 ( edit-pipeline svndiff1 accepts-svndiff2 absent-entries depth mergeinfo log-revprops ) 44:svn+ssh://rc@code.example.com/TestRepo/trunk 34:SVN/1.14.5 (x64-microsoft-windows) ( ) )",
b"( 2 ( edit-pipeline svndiff1 accepts-svndiff2 absent-entries depth mergeinfo log-revprops ) 44:svn+ssh://rc@code.example.com/TestRepo/trunk 34:SVN/1.14.5 (x64-microsoft-windows) ( ) ) ",
None,
),
],

View file

@ -67,7 +67,7 @@ def _commits_as_dict(event, commit_ids, repos):
cs_data = {
"raw_id": commit_id,
"short_id": commit_id,
"branch": None,
"branches": [],
"git_ref_change": "tag_add",
"message": f"Added new tag {raw_id}",
"author": event.actor.full_contact,
@ -81,7 +81,7 @@ def _commits_as_dict(event, commit_ids, repos):
cs_data = {
"raw_id": commit_id,
"short_id": commit_id,
"branch": None,
"branches": [],
"git_ref_change": "branch_delete",
"message": f"Deleted branch {raw_id}",
"author": event.actor.full_contact,
@ -95,7 +95,6 @@ def _commits_as_dict(event, commit_ids, repos):
cs = vcs_repo.get_commit(commit_id)
except CommitDoesNotExistError:
continue # maybe its in next repo
cs_data = cs.__json__()
cs_data["refs"] = cs._get_refs()
@ -380,17 +379,19 @@ class RepoPushEvent(RepoVCSEvent):
data = super().as_dict()
def branch_url(branch_name):
return "{}/changelog?branch={}".format(data["repo"]["url"], branch_name)
return f"{data['repo']['url']}/changelog?branch={branch_name}"
def tag_url(tag_name):
return "{}/files/{}/".format(data["repo"]["url"], tag_name)
return f"{data['repo']['url']}/files/{tag_name}/"
commits = _commits_as_dict(self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
last_branch = None
# fill branches for every single commit
last_branch = []
for commit in reversed(commits):
commit["branch"] = commit["branch"] or last_branch
last_branch = commit["branch"]
commit["branches"] = commit["branches"] or last_branch
last_branch = commit["branches"]
issues = _issues_as_dict(commits)
branches = set()
@ -399,8 +400,9 @@ class RepoPushEvent(RepoVCSEvent):
if commit["refs"]["tags"]:
for tag in commit["refs"]["tags"]:
tags.add(tag)
if commit["branch"]:
branches.add(commit["branch"])
if commit["branches"]:
for branch in commit["branches"]:
branches.add(branch)
# maybe we have branches in new_refs ?
try:

View file

@ -230,16 +230,18 @@ class CommitParsingDataHandler(object):
# special case for GIT that allows creating tags,
# deleting branches without associated commit
continue
commit_branch = commit["branch"]
if commit_branch not in branches_commits:
_branch = branch_data[commit_branch] if commit_branch else commit_branch
branch_commits = {"branch": _branch, "branch_head": "", "commits": []}
branches_commits[commit_branch] = branch_commits
maybe_commit_branches = commit["branches"]
branch_commits = branches_commits[commit_branch]
branch_commits["commits"].append(commit)
branch_commits["branch_head"] = commit["raw_id"]
for commit_branch in maybe_commit_branches:
if commit_branch not in branches_commits:
_branch = branch_data[commit_branch] if commit_branch else commit_branch
branch_commits = {"branch": _branch, "branch_head": "", "commits": []}
branches_commits[commit_branch] = branch_commits
branch_commits = branches_commits[commit_branch]
branch_commits["commits"].append(commit)
branch_commits["branch_head"] = commit["raw_id"]
return branches_commits

View file

@ -106,6 +106,7 @@ def get_logger(obj):
# init main celery app
celery_app = Celery()
celery_app.user_options["preload"].add(preload_option_ini)
celery_app.user_options["preload"].add(preload_option_ini_var)
@ -215,6 +216,7 @@ def task_success_signal(result, **kwargs):
@signals.task_retry.connect
def task_retry_signal(request, reason, einfo, **kwargs):
log.warning("Task: %s failed !! reason: %s", request, reason)
meta.Session.remove()
closer = celery_app.conf["PYRAMID_CLOSER"]
if closer:
@ -234,7 +236,7 @@ def task_failure_signal(task_id, exception, args, kwargs, traceback, einfo, **ka
store_exception(id(exc_info), exc_info, prefix="rhodecode-celery")
statsd = StatsdClient.statsd
if statsd:
exc_type = "{}.{}".format(einfo.__class__.__module__, einfo.__class__.__name__)
exc_type = f"{einfo.__class__.__module__}.{einfo.__class__.__name__}"
statsd.incr("rhodecode_exception_total", tags=["exc_source:celery", "type:{}".format(exc_type)])
closer = celery_app.conf["PYRAMID_CLOSER"]

View file

@ -750,7 +750,7 @@ def _get_diffset(
source_ref_id = pull_request.source_ref_parts.commit_id
target_ref_id = pull_request.target_ref_parts.commit_id
pre_load = ["author", "date", "message", "branch", "parents"]
pre_load = ["author", "date", "message", "branches", "parents"]
target_commit_final = target_repo.get_commit(commit_id=safe_str(target_ref_id), pre_load=pre_load)
source_commit_final = source_repo.get_commit(commit_id=safe_str(source_ref_id), pre_load=pre_load)

View file

@ -391,13 +391,10 @@ class DbManage(object):
self.sa.add(hggit)
# set svn branch defaults
branches = ["/branches/*", "/trunk"]
tags = ["/tags/*"]
for branch in branches:
for branch in RhodeCodeUi.SVN_BRANCHES_PATTERNS:
settings_model.create_ui_section_value(RhodeCodeUi.SVN_BRANCH_ID, branch)
for tag in tags:
for tag in RhodeCodeUi.SVN_TAGS_PATTERNS:
settings_model.create_ui_section_value(RhodeCodeUi.SVN_TAG_ID, tag)
def create_auth_plugin_options(self, skip_existing=False):

View file

@ -694,6 +694,7 @@ def get_lexer_safe(mimetype=None, filepath=None):
defaulting to plain text if none could be found
"""
lexer = None
try:
if mimetype:
lexer = get_lexer_for_mimetype(mimetype)

View file

@ -782,8 +782,10 @@ def get_custom_lexer(extension):
from pygments import lexers
# custom override made by RhodeCode
if extension in ["mako"]:
if extension.lower() in ["mako"]:
return lexers.get_lexer_by_name("html+mako")
elif extension.lower() in ["jenkinsfile"]:
return lexers.get_lexer_by_name("groovy")
# check if we didn't define this extension as other lexer
extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, "EXTRA_LEXERS", None)

View file

@ -76,11 +76,13 @@ class Reference:
def branch(self):
if self.type == "branch":
return self.name
return None
@property
def bookmark(self):
if self.type == "book":
return self.name
return None
@property
def to_str(self):
@ -334,7 +336,8 @@ class BaseCommit:
"""
repository = None
branch = None
branches: list | None = None
tags: list | None = None
"""
Depending on the backend this should be set to the branch name of the
@ -375,7 +378,7 @@ class BaseCommit:
"date": self.date,
"author": self.author,
"parents": parents,
"branch": self.branch,
"branches": self.branches,
}
def __getstate__(self):
@ -392,9 +395,9 @@ class BaseCommit:
def _get_refs(self):
return {
"branches": [self.branch] if self.branch else [],
"branches": self.branches if self.branches else [],
"tags": self.tags if self.tags else [],
"bookmarks": getattr(self, "bookmarks", []),
"tags": self.tags,
}
@LazyProperty
@ -698,12 +701,12 @@ class BaseCommit:
return self._find_next(indexes, branch)
def _find_next(self, indexes, branch=None):
if branch and self.branch != branch:
if branch and branch not in self.branches:
raise VCSError("Branch option used on commit not belonging to that branch")
for next_idx in indexes:
commit = self.repository.get_commit(commit_idx=next_idx)
if branch and branch != commit.branch:
if branch and branch not in commit.branches:
continue
return commit
raise CommitDoesNotExistError
@ -725,7 +728,7 @@ class BaseCommit:
def walk(self, top_url=b""):
"""
Similar to os.walk method. Insted of filesystem it walks through
Similar to os.walk method. Instead of filesystem it walks through
commit starting at given ``topurl``. Returns generator of tuples
(top_node, dirnodes, filenodes).
"""
@ -796,6 +799,10 @@ class BaseCommit:
warnings.warn("Use get_path_commit instead", DeprecationWarning)
return self.get_path_commit(path)
@LazyProperty
def last_branch(self) -> str | None:
return self.branches[0] if self.branches else None
class BaseRepository(object):
"""
@ -1057,7 +1064,7 @@ class BaseRepository(object):
"""
Allows index based access to the commit objects of this repository.
"""
pre_load = ["author", "branch", "date", "message", "parents"]
pre_load = ["author", "branches", "date", "message", "parents"]
if isinstance(key, slice):
return self._get_range(key, pre_load)
return self.get_commit(commit_idx=key, pre_load=pre_load)
@ -1672,7 +1679,15 @@ class EmptyCommit(BaseCommit):
"""
def __init__(
self, commit_id=EMPTY_COMMIT_ID, repo=None, alias=None, idx=-1, message="", author="", date=None, branch=None
self,
commit_id=EMPTY_COMMIT_ID,
repo=None,
alias=None,
idx=-1,
message="",
author="",
date=None,
branch: list = None,
):
self._empty_commit_id = commit_id
# TODO: johbo: Solve idx parameter, default value does not make
@ -1683,7 +1698,9 @@ class EmptyCommit(BaseCommit):
self.date = date or datetime.datetime.fromtimestamp(0)
self.repository = repo
self.alias = alias
self._branch = branch
if branch and not isinstance(branch, list):
branch = [branch]
self._branches = branch or []
@LazyProperty
def raw_id(self):
@ -1696,14 +1713,23 @@ class EmptyCommit(BaseCommit):
@LazyProperty
def branch(self):
raise ValueError("Deprecated usage of .branch property")
return self._branches[self.idx]
# If branch was explicitly set, return it
if self._branch:
return self._branch
if self.alias:
branches = self.branches
if branches:
return branches[:1]
else:
from rhodecode.lib.vcs.backends import get_backend
return get_backend(self.alias).DEFAULT_BRANCH_NAME
return [get_backend(self.alias).DEFAULT_BRANCH_NAME]
@LazyProperty
def branches(self) -> list[str]:
# If branches was explicitly set, return it
if self._branches:
return self._branches
return []
@LazyProperty
def short_id(self):

View file

@ -96,8 +96,8 @@ class GitCommit(base.BaseCommit):
value = utcdate_fromtimestamp(*value)
elif attr == "parents":
value = self._make_commits(value)
elif attr == "branch":
value = self._set_branch(value)
elif attr == "branches":
value = value
self.__dict__[attr] = value
@LazyProperty
@ -154,15 +154,10 @@ class GitCommit(base.BaseCommit):
branches.append(name)
return branches
def _set_branch(self, branches):
if branches:
# actually commit can have multiple branches in git
return safe_str(branches[0])
@LazyProperty
def branch(self):
branches = self._remote.branch(self.raw_id)
return self._set_branch(branches)
def branches(self) -> list[str]:
branches = self._remote.branches(self.raw_id)
return branches
def _get_path_tree_id_and_type(self, path: bytes):
if path in self._path_type_cache:

View file

@ -78,8 +78,10 @@ class MercurialCommit(base.BaseCommit):
result = self._remote.bulk_request(self.raw_id, pre_load)
for attr, value in result.items():
if attr in ["author", "branch", "message"]:
if attr in ["author", "message"]:
value = safe_str(value)
elif attr in ["branches"]:
value = list(value)
elif attr == "affected_files":
value = list(map(safe_str, value))
elif attr == "date":
@ -96,8 +98,8 @@ class MercurialCommit(base.BaseCommit):
return tags
@LazyProperty
def branch(self):
return safe_str(self._remote.ctx_branch(self.raw_id))
def branches(self) -> list[str]:
return self._remote.ctx_branch(self.raw_id)
@LazyProperty
def bookmarks(self):

View file

@ -78,6 +78,10 @@ class SubversionCommit(base.BaseCommit):
def _properties(self):
return self._remote.revision_properties(self._svn_rev)
@LazyProperty
def branches(self) -> list[str]:
return self._remote.revision_branches(self._svn_rev)
@LazyProperty
def parents(self):
parent_idx = self.idx - 1

View file

@ -46,7 +46,6 @@ from rhodecode.lib.vcs.exceptions import (
NodeDoesNotExistError,
)
log = logging.getLogger(__name__)
@ -127,7 +126,9 @@ class SubversionRepository(base.BaseRepository):
@LazyProperty
def branches(self):
return self._tags_or_branches("vcs_svn_branch")
from rhodecode.model.settings import VcsSettingsModel
return self._tags_or_branches(VcsSettingsModel.SVN_BRANCH_SECTION)
@LazyProperty
def branches_closed(self):
@ -147,7 +148,9 @@ class SubversionRepository(base.BaseRepository):
@LazyProperty
def tags(self):
return self._tags_or_branches("vcs_svn_tag")
from rhodecode.model.settings import VcsSettingsModel
return self._tags_or_branches(VcsSettingsModel.SVN_TAG_SECTION)
def _tags_or_branches(self, config_section):
found_items = {}

View file

@ -54,6 +54,8 @@ EXCEPTIONS_MAP = {
def _remote_call(url, payload, exceptions_map, session, retries=3):
response = None
for attempt in range(retries):
try:
response = session.post(url, data=msgpack.packb(payload))
@ -73,6 +75,11 @@ def _remote_call(url, payload, exceptions_map, session, retries=3):
else:
raise
if response is None:
e = pycurl.E_RECV_ERROR
log.error("Failed to connect to remote server: %s", e)
raise exceptions.HttpVCSCommunicationError(e)
if response.status_code >= 400:
content_type = response.content_type
log.error("Call to %s returned non 200 HTTP code: %s [%s]", url, response.status_code, content_type)

View file

@ -501,7 +501,10 @@ class RhodeCodeUi(Base, BaseModel):
# SVN PATTERNS
SVN_BRANCH_ID = "vcs_svn_branch"
SVN_BRANCHES_PATTERNS = ["/branches/*", "/trunk"]
SVN_TAG_ID = "vcs_svn_tag"
SVN_TAGS_PATTERNS = ["/tags/*"]
ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
@ -2685,7 +2688,7 @@ class Repository(Base, BaseModel):
empty = scm_repo is None or scm_repo.is_empty()
if not empty:
cs_cache = scm_repo.get_commit(pre_load=["author", "date", "message", "parents", "branch"])
cs_cache = scm_repo.get_commit(pre_load=["author", "date", "message", "parents", "branches"])
repo_commit_count = scm_repo.count()
else:
cs_cache = EmptyCommit()

View file

@ -52,6 +52,7 @@ from rhodecode.lib.pyramid_utils import get_current_request
from rhodecode import BACKENDS
from rhodecode.lib import helpers
from rhodecode.model import validators as v
from rhodecode.model.settings import VcsSettingsModel
log = logging.getLogger(__name__)
@ -477,8 +478,8 @@ def ApplicationUiSettingsForm(localizer):
class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
extensions_hggit = v.StringBoolean(if_missing=False)
new_svn_branch = v.ValidSvnPattern(localizer, section="vcs_svn_branch")
new_svn_tag = v.ValidSvnPattern(localizer, section="vcs_svn_tag")
new_svn_branch = v.ValidSvnPattern(localizer, section=VcsSettingsModel.SVN_BRANCH_SECTION)
new_svn_tag = v.ValidSvnPattern(localizer, section=VcsSettingsModel.SVN_TAG_SECTION)
return _ApplicationUiSettingsForm
@ -488,8 +489,8 @@ def RepoVcsSettingsForm(localizer, repo_name):
class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
inherit_global_settings = v.StringBoolean(if_missing=False)
new_svn_branch = v.ValidSvnPattern(localizer, section="vcs_svn_branch", repo_name=repo_name)
new_svn_tag = v.ValidSvnPattern(localizer, section="vcs_svn_tag", repo_name=repo_name)
new_svn_branch = v.ValidSvnPattern(localizer, section=VcsSettingsModel.SVN_BRANCH_SECTION, repo_name=repo_name)
new_svn_tag = v.ValidSvnPattern(localizer, section=VcsSettingsModel.SVN_TAG_SECTION, repo_name=repo_name)
return _RepoVcsSettingsForm

View file

@ -1221,7 +1221,7 @@ class PullRequestModel(BaseModel):
# re-compute commit ids
old_commit_ids = pull_request.revisions
pre_load = ["author", "date", "message", "branch"]
pre_load = ["author", "date", "message", "branches"]
commit_ranges = target_repo.compare(
target_commit.raw_id, source_commit.raw_id, source_repo, merge=True, pre_load=pre_load
)
@ -2338,7 +2338,7 @@ class MergeCheck(object):
# for mercurial we can always figure out the branch from the commit
# in case of bookmark
target_commit = pull_request.target_repo.get_commit(target_commit_id)
branch_name = target_commit.branch
branch_name = target_commit.last_branch
rule, branch_perm = auth_user.get_rule_and_branch_permission(pull_request.target_repo.repo_name, branch_name)
if branch_perm and branch_perm == "branch.none":

View file

@ -489,7 +489,7 @@ class ScmModel(BaseModel):
imc.change(FileNode(f_path, content, mode=commit.get_file_mode(f_path)))
try:
# TODO: handle pre-push action !
tip = imc.commit(message=message, author=author, parents=[commit], branch=branch or commit.branch)
tip = imc.commit(message=message, author=author, parents=[commit], branch=branch or commit.last_branch)
except Exception as e:
log.error(traceback.format_exc())
raise IMCCommitError(str(e))
@ -831,7 +831,7 @@ class ScmModel(BaseModel):
imc.add(FileNode(path, content=content))
# TODO: handle pre push scenario
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.branch)
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.last_branch)
self.mark_for_invalidation(repo.repo_name)
if trigger_push_hook:
@ -874,7 +874,7 @@ class ScmModel(BaseModel):
try:
# TODO: handle pre push scenario commit changes
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.branch)
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.last_branch)
except NodeNotChangedError:
raise
except Exception as e:
@ -910,7 +910,7 @@ class ScmModel(BaseModel):
imc.change(file_node)
try:
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.branch)
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.last_branch)
except NodeNotChangedError:
raise
except Exception as e:
@ -963,7 +963,7 @@ class ScmModel(BaseModel):
imc.remove(FileNode(path, content=content))
# TODO: handle pre push scenario
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.branch)
tip = imc.commit(message=message, author=author, parents=parents, branch=parent_commit.last_branch)
self.mark_for_invalidation(repo.repo_name)
if trigger_push_hook:

View file

@ -337,7 +337,7 @@ def assert_repo_settings(func):
return _wrapper
class IssueTrackerSettingsModel(object):
class IssueTrackerSettingsModel:
INHERIT_SETTINGS = "inherit_issue_tracker_settings"
SETTINGS_PREFIX = "issuetracker_"
@ -450,7 +450,7 @@ class IssueTrackerSettingsModel(object):
return setting
class VcsSettingsModel(object):
class VcsSettingsModel:
INHERIT_SETTINGS = "inherit_vcs_settings"
GENERAL_SETTINGS = (
"use_outdated_comments",

View file

@ -45,6 +45,9 @@ function registerRCRoutes() {
pyroutes.register('admin_security_modify_allowed_vcs_client_versions', '/_admin/security/modify/allowed_vcs_client_versions', []);
pyroutes.register('admin_security_update', '/_admin/security/audit/update', []);
pyroutes.register('admin_settings', '/_admin/settings', []);
pyroutes.register('admin_settings_ai', '/_admin/settings/ai', []);
pyroutes.register('admin_settings_ai_update', '/_admin/settings/ai/update', []);
pyroutes.register('admin_settings_ai_update_models', '/_admin/settings/ai/model/version', []);
pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
@ -277,6 +280,7 @@ function registerRCRoutes() {
pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
pyroutes.register('pullrequest_start_ai_code_review', '/%(repo_name)s/pull-request/%(pull_request_id)s/ai/review', ['repo_name', 'pull_request_id']);
pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']);
pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
pyroutes.register('register', '/_admin/register', []);

View file

@ -150,7 +150,12 @@
</div>
</div>
<div class="label">
<span class="help-block">${_('Patterns for identifying SVN branches and tags. For recursive search, use "*". Eg.: "/branches/*"')}</span>
<span class="help-block">
${_('Patterns for identifying SVN branches and tags.')}
${_('Examples defaults')}:<br/>
Branches: ${", ".join(c.svn_default_branches)}<br/>
Tags: ${", ".join(c.svn_default_tags)}
</span>
</div>
<div class="field branch_patterns">

View file

@ -333,7 +333,7 @@
var _html = '';
_html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
.replace('__branch__', data.results[0].branch)
.replace('__branch__', data.results[0].branches.join(","))
.replace('__rev__', 'r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0, 6)))
.replace('__title__', data.results[0].message)
.replace('__url__', pyroutes.url('repo_commit', {
@ -342,7 +342,7 @@
}));
_html += ' | ';
_html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
.replace('__branch__', data.results[1].branch)
.replace('__branch__', data.results[1].branches.join(","))
.replace('__rev__', 'r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0, 6)))
.replace('__title__', data.results[1].message)
.replace('__url__', pyroutes.url('repo_commit', {
@ -380,7 +380,7 @@
var _html = '';
_html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
.replace('__branch__', data.results[0].branch)
.replace('__branch__', data.results[0].branches.join(","))
.replace('__rev__', 'r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0, 6)))
.replace('__title__', data.results[0].message)
.replace('__url__', pyroutes.url('repo_commit', {
@ -389,7 +389,7 @@
}));
_html += ' | ';
_html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
.replace('__branch__', data.results[1].branch)
.replace('__branch__', data.results[1].branches.join(","))
.replace('__rev__', 'r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0, 6)))
.replace('__title__', data.results[1].message)
.replace('__url__', pyroutes.url('repo_commit', {

View file

@ -104,11 +104,11 @@
%endif
## branch
%if commit.branch:
<span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
<a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
%for branch in commit.branches:
<span class="tag branchtag" title="${h.tooltip(_('Branch %s') % branch)}">
<a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=branch))}"><i class="icon-code-fork"></i>${h.shorter(branch)}</a>
</span>
%endif
%endfor
## bookmarks
%if h.is_hg(c.rhodecode_repo):

View file

@ -5,22 +5,6 @@
fileTreeRefs = {}
</script>
% if h.is_svn(c.rhodecode_repo):
## since SVN doesn't have an commit<->refs association, we simply inject it
## based on our at_rev marker
% if at_rev and at_rev.startswith('branches/'):
<%
commit.branch = at_rev
%>
% endif
% if at_rev and at_rev.startswith('tags/'):
<%
commit.tags.append(at_rev)
%>
% endif
% endif
%if commit.merge:
<span class="mergetag tag">
<i class="icon-merge">${_('merge')}</i>
@ -47,13 +31,13 @@
</script>
%endfor
%if commit.branch:
<span class="branchtag tag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
<a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id,_query=dict(at=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
%for branch in commit.branches:
<span class="branchtag tag" title="${h.tooltip(_('Branch %s') % branch)}">
<a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id,_query=dict(at=branch))}"><i class="icon-code-fork"></i>${h.shorter(branch)}</a>
</span>
<script>
fileTreeRefs["${commit.branch}"] = {raw_id: "${commit.raw_id}", type:"branch", text: "${commit.branch}"};
fileTreeRefs["${branch}"] = {raw_id: "${commit.raw_id}", type:"branch", text: "${branch}"};
</script>
%endif
%endfor
</%def>

View file

@ -25,12 +25,12 @@
<div class="box">
<div class="edit-file-title">
<span class="title-heading">${_('Add new file')} @ <code>${h.show_id(c.commit)}</code></span>
% if c.commit.branch:
<span class="title-heading">${_('Add new file')}</code></span>
% for branch in c.commit.branches:
<span class="tag branchtag">
<i class="icon-branch"></i> ${c.commit.branch}
<i class="icon-branch"></i> ${branch}
</span>
% endif
% endfor
</div>
${h.secure_form(h.route_path('repo_files_create_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)}

View file

@ -22,12 +22,12 @@
<div class="box">
<div class="edit-file-title">
<span class="title-heading">${_('Delete file')} @ <code>${h.show_id(c.commit)}</code></span>
% if c.commit.branch:
<span class="title-heading">${_('Deleting file')}</span>
% for branch in c.commit.branches:
<span class="tag branchtag">
<i class="icon-branch"></i> ${c.commit.branch}
<i class="icon-branch"></i> ${branch}
</span>
% endif
% endfor
</div>
${h.secure_form(h.route_path('repo_files_delete_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)}

View file

@ -25,12 +25,12 @@
<div class="box">
<div class="edit-file-title">
<span class="title-heading">${_('Edit file')} @ <code>${h.show_id(c.commit)}</code></span>
% if c.commit.branch:
<span class="title-heading">${_('Editing file')}</code></span>
% for branch in c.commit.branches:
<span class="tag branchtag">
<i class="icon-branch"></i> ${c.commit.branch}
<i class="icon-branch"></i> ${branch}
</span>
% endif
% endfor
</div>
${h.secure_form(h.route_path('repo_files_update_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)}

View file

@ -27,7 +27,7 @@
</a>
% else:
<a class="btn btn-default" href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}">
${_('Download file')}
${_('Download')}
</a>
% endif
@ -40,9 +40,8 @@
${h.link_to(_('Delete'), h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _query=query),class_="btn btn-danger")}
% else:
<a class="btn btn-default" href="${h.route_path('repo_files_edit_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _query=query)}">
${_('Edit on branch: ')}<code>${c.branch_name}</code>
${_('Edit')}
</a>
<a class="btn btn-danger" href="${h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _query=query)}">
${_('Delete')}
</a>

View file

@ -23,15 +23,15 @@
## Template for uploads
<div class="edit-file-title">
% if c.replace_binary:
<span class="title-heading">${_('Replace content of')} <b>${c.f_path}</b> @ <code>${h.show_id(c.commit)}</code></span>
<span class="title-heading">${_('Replace content of')} <b>${c.f_path}</b> </code></span>
% else:
<span class="title-heading">${_('Upload new file')} @ <code>${h.show_id(c.commit)}</code></span>
<span class="title-heading">${_('Upload new file')} </span>
% endif
% if c.commit.branch:
% for branch in c.commit.branches:
<span class="tag branchtag">
<i class="icon-branch"></i> ${c.commit.branch}
<i class="icon-branch"></i> ${branch}
</span>
% endif
% endfor
</div>
% if not c.replace_binary:

View file

@ -73,11 +73,11 @@
%endfor
## branch
%if cs.branch:
<span class="branchtag tag" title="${h.tooltip(_('Branch %s') % cs.branch)}">
<a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=cs.branch))}"><i class="icon-code-fork"></i>${h.shorter(cs.branch)}</a>
%for branch in cs.branches:
<span class="branchtag tag" title="${h.tooltip(_('Branch %s') % branch)}">
<a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=branch))}"><i class="icon-code-fork"></i>${h.shorter(branch)}</a>
</span>
%endif
%endfor
</div>
</td>
<td class="td-comments">

View file

@ -1 +1,92 @@
{"results": [{"text": "Changesets", "children": [{"text": "r15:16", "at_rev": "", "type": "sha", "id": "16"}, {"text": "r12:13", "at_rev": "", "type": "sha", "id": "13"}, {"text": "r7:8", "at_rev": "", "type": "sha", "id": "8"}, {"text": "r3:4", "at_rev": "", "type": "sha", "id": "4"}, {"text": "r2:3", "at_rev": "", "type": "sha", "id": "3"}]}, {"text": "Branches", "children": [{"text": "branches/add-docs", "at_rev": "branches/add-docs", "type": "branch", "id": "26"}, {"text": "branches/argparse", "at_rev": "branches/argparse", "type": "branch", "id": "26"}, {"text": "trunk", "at_rev": "trunk", "type": "branch", "id": "26"}]}, {"text": "Tags", "children": [{"text": "tags/v0.1", "at_rev": "tags/v0.1", "type": "tag", "id": "26"}, {"text": "tags/v0.2", "at_rev": "tags/v0.2", "type": "tag", "id": "26"}, {"text": "tags/v0.3", "at_rev": "tags/v0.3", "type": "tag", "id": "26"}, {"text": "tags/v0.5", "at_rev": "tags/v0.5", "type": "tag", "id": "26"}]}], "more": false}
{
"results": [
{
"text": "Changesets",
"children": [
{
"text": "r15:16 (trunk)",
"at_rev": "",
"type": "sha",
"id": "16"
},
{
"text": "r12:13 (trunk)",
"at_rev": "",
"type": "sha",
"id": "13"
},
{
"text": "r7:8 (trunk)",
"at_rev": "",
"type": "sha",
"id": "8"
},
{
"text": "r3:4 (trunk)",
"at_rev": "",
"type": "sha",
"id": "4"
},
{
"text": "r2:3 (trunk)",
"at_rev": "",
"type": "sha",
"id": "3"
}
]
},
{
"text": "Branches",
"children": [
{
"text": "branches/add-docs",
"at_rev": "branches/add-docs",
"type": "branch",
"id": "26"
},
{
"text": "branches/argparse",
"at_rev": "branches/argparse",
"type": "branch",
"id": "26"
},
{
"text": "trunk",
"at_rev": "trunk",
"type": "branch",
"id": "26"
}
]
},
{
"text": "Tags",
"children": [
{
"text": "tags/v0.1",
"at_rev": "tags/v0.1",
"type": "tag",
"id": "26"
},
{
"text": "tags/v0.2",
"at_rev": "tags/v0.2",
"type": "tag",
"id": "26"
},
{
"text": "tags/v0.3",
"at_rev": "tags/v0.3",
"type": "tag",
"id": "26"
},
{
"text": "tags/v0.5",
"at_rev": "tags/v0.5",
"type": "tag",
"id": "26"
}
]
}
],
"more": false
}

View file

@ -1 +1,58 @@
{"results": [{"text": "Changesets", "children": [{"text": "r382:383", "at_rev": "", "type": "sha", "id": "383"}, {"text": "r323:324", "at_rev": "", "type": "sha", "id": "324"}, {"text": "r322:323", "at_rev": "", "type": "sha", "id": "323"}, {"text": "r299:300", "at_rev": "", "type": "sha", "id": "300"}, {"text": "r277:278", "at_rev": "", "type": "sha", "id": "278"}, {"text": "r273:274", "at_rev": "", "type": "sha", "id": "274"}, {"text": "r270:271", "at_rev": "", "type": "sha", "id": "271"}, {"text": "r269:270", "at_rev": "", "type": "sha", "id": "270"}, {"text": "r263:264", "at_rev": "", "type": "sha", "id": "264"}, {"text": "r261:262", "at_rev": "", "type": "sha", "id": "262"}, {"text": "r251:252", "at_rev": "", "type": "sha", "id": "252"}, {"text": "r208:209", "at_rev": "", "type": "sha", "id": "209"}, {"text": "r202:203", "at_rev": "", "type": "sha", "id": "203"}, {"text": "r173:174", "at_rev": "", "type": "sha", "id": "174"}, {"text": "r172:173", "at_rev": "", "type": "sha", "id": "173"}, {"text": "r171:172", "at_rev": "", "type": "sha", "id": "172"}, {"text": "r145:146", "at_rev": "", "type": "sha", "id": "146"}, {"text": "r144:145", "at_rev": "", "type": "sha", "id": "145"}, {"text": "r140:141", "at_rev": "", "type": "sha", "id": "141"}, {"text": "r134:135", "at_rev": "", "type": "sha", "id": "135"}, {"text": "r107:108", "at_rev": "", "type": "sha", "id": "108"}, {"text": "r106:107", "at_rev": "", "type": "sha", "id": "107"}, {"text": "r100:101", "at_rev": "", "type": "sha", "id": "101"}, {"text": "r94:95", "at_rev": "", "type": "sha", "id": "95"}, {"text": "r85:86", "at_rev": "", "type": "sha", "id": "86"}, {"text": "r73:74", "at_rev": "", "type": "sha", "id": "74"}, {"text": "r72:73", "at_rev": "", "type": "sha", "id": "73"}, {"text": "r71:72", "at_rev": "", "type": "sha", "id": "72"}, {"text": "r69:70", "at_rev": "", "type": "sha", "id": "70"}, {"text": "r67:68", "at_rev": "", "type": "sha", "id": "68"}, {"text": "r63:64", "at_rev": "", "type": "sha", "id": "64"}, {"text": "r62:63", "at_rev": "", "type": "sha", "id": "63"}, {"text": "r61:62", "at_rev": "", "type": "sha", "id": "62"}, {"text": "r50:51", "at_rev": "", "type": "sha", "id": "51"}, {"text": "r49:50", "at_rev": "", "type": "sha", "id": "50"}, {"text": "r48:49", "at_rev": "", "type": "sha", "id": "49"}, {"text": "r47:48", "at_rev": "", "type": "sha", "id": "48"}, {"text": "r46:47", "at_rev": "", "type": "sha", "id": "47"}, {"text": "r45:46", "at_rev": "", "type": "sha", "id": "46"}, {"text": "r41:42", "at_rev": "", "type": "sha", "id": "42"}, {"text": "r39:40", "at_rev": "", "type": "sha", "id": "40"}, {"text": "r37:38", "at_rev": "", "type": "sha", "id": "38"}, {"text": "r25:26", "at_rev": "", "type": "sha", "id": "26"}, {"text": "r23:24", "at_rev": "", "type": "sha", "id": "24"}, {"text": "r8:9", "at_rev": "", "type": "sha", "id": "9"}, {"text": "r7:8", "at_rev": "", "type": "sha", "id": "8"}]}, {"text": "Branches", "children": []}, {"text": "Tags", "children": []}], "more": false}
{
"results": [
{
"text": "Changesets",
"children": [
{ "text": "r382:383 (trunk)", "at_rev": "", "type": "sha", "id": "383" },
{ "text": "r323:324 (trunk)", "at_rev": "", "type": "sha", "id": "324" },
{ "text": "r322:323 (trunk)", "at_rev": "", "type": "sha", "id": "323" },
{ "text": "r299:300 (trunk)", "at_rev": "", "type": "sha", "id": "300" },
{ "text": "r277:278 (trunk)", "at_rev": "", "type": "sha", "id": "278" },
{ "text": "r273:274 (trunk)", "at_rev": "", "type": "sha", "id": "274" },
{ "text": "r270:271 (trunk)", "at_rev": "", "type": "sha", "id": "271" },
{ "text": "r269:270 (trunk)", "at_rev": "", "type": "sha", "id": "270" },
{ "text": "r263:264 (trunk)", "at_rev": "", "type": "sha", "id": "264" },
{ "text": "r261:262 (trunk)", "at_rev": "", "type": "sha", "id": "262" },
{ "text": "r251:252 (trunk)", "at_rev": "", "type": "sha", "id": "252" },
{ "text": "r208:209 (trunk)", "at_rev": "", "type": "sha", "id": "209" },
{ "text": "r202:203 (trunk)", "at_rev": "", "type": "sha", "id": "203" },
{ "text": "r173:174 (trunk)", "at_rev": "", "type": "sha", "id": "174" },
{ "text": "r172:173 (trunk)", "at_rev": "", "type": "sha", "id": "173" },
{ "text": "r171:172 (trunk)", "at_rev": "", "type": "sha", "id": "172" },
{ "text": "r145:146 (trunk)", "at_rev": "", "type": "sha", "id": "146" },
{ "text": "r144:145 (trunk)", "at_rev": "", "type": "sha", "id": "145" },
{ "text": "r140:141 (trunk)", "at_rev": "", "type": "sha", "id": "141" },
{ "text": "r134:135 (trunk)", "at_rev": "", "type": "sha", "id": "135" },
{ "text": "r107:108 (trunk)", "at_rev": "", "type": "sha", "id": "108" },
{ "text": "r106:107 (trunk)", "at_rev": "", "type": "sha", "id": "107" },
{ "text": "r100:101 (trunk)", "at_rev": "", "type": "sha", "id": "101" },
{ "text": "r94:95 (trunk)", "at_rev": "", "type": "sha", "id": "95" },
{ "text": "r85:86 (trunk)", "at_rev": "", "type": "sha", "id": "86" },
{ "text": "r73:74 (trunk)", "at_rev": "", "type": "sha", "id": "74" },
{ "text": "r72:73 (trunk)", "at_rev": "", "type": "sha", "id": "73" },
{ "text": "r71:72 (trunk)", "at_rev": "", "type": "sha", "id": "72" },
{ "text": "r69:70 (trunk)", "at_rev": "", "type": "sha", "id": "70" },
{ "text": "r67:68 (trunk)", "at_rev": "", "type": "sha", "id": "68" },
{ "text": "r63:64 (trunk)", "at_rev": "", "type": "sha", "id": "64" },
{ "text": "r62:63 (trunk)", "at_rev": "", "type": "sha", "id": "63" },
{ "text": "r61:62 (trunk)", "at_rev": "", "type": "sha", "id": "62" },
{ "text": "r50:51 (trunk)", "at_rev": "", "type": "sha", "id": "51" },
{ "text": "r49:50 (trunk)", "at_rev": "", "type": "sha", "id": "50" },
{ "text": "r48:49 (trunk)", "at_rev": "", "type": "sha", "id": "49" },
{ "text": "r47:48 (trunk)", "at_rev": "", "type": "sha", "id": "48" },
{ "text": "r46:47 (trunk)", "at_rev": "", "type": "sha", "id": "47" },
{ "text": "r45:46 (trunk)", "at_rev": "", "type": "sha", "id": "46" },
{ "text": "r41:42 (trunk)", "at_rev": "", "type": "sha", "id": "42" },
{ "text": "r39:40 (trunk)", "at_rev": "", "type": "sha", "id": "40" },
{ "text": "r37:38 (trunk)", "at_rev": "", "type": "sha", "id": "38" },
{ "text": "r25:26 (trunk)", "at_rev": "", "type": "sha", "id": "26" },
{ "text": "r23:24 (trunk)", "at_rev": "", "type": "sha", "id": "24" },
{ "text": "r8:9 (trunk)", "at_rev": "", "type": "sha", "id": "9" },
{ "text": "r7:8 (trunk)", "at_rev": "", "type": "sha", "id": "8" }
]
},
{ "text": "Branches", "children": [] },
{ "text": "Tags", "children": [] }
],
"more": false
}

View file

@ -736,10 +736,17 @@ class VcsBackend(object):
def _next_repo_name(self):
return "{}_{}".format(self.invalid_repo_name.sub("_", self._test_name), len(self._cleanup_repos))
def add_file(self, repo, filename, content="Test content\n"):
def add_file(
self,
repo,
filename,
content="Test content\n",
msg="Automatic commit from vcsbackend fixture",
author="Automatic <automatic@rhodecode.com>",
):
imc = repo.in_memory_commit
imc.add(FileNode(safe_bytes(filename), content=safe_bytes(content)))
imc.commit(message="Automatic commit from vcsbackend fixture", author="Automatic <automatic@rhodecode.com>")
imc.commit(message=msg, author=author)
def ensure_file(self, filename, content="Test content\n"):
assert self._cleanup_repos, "Avoid writing into vcs_test repos"

View file

@ -144,10 +144,10 @@ def test_webook_parse_url_for_push_event(baseapp, repo_push_event, base_data, te
base_data["push"] = {
"branches": [{"name": "stable"}, {"name": "dev"}],
"commits": [
{"branch": "stable", "raw_id": "stable-xxx"},
{"branch": "stable", "raw_id": "stable-yyy"},
{"branch": "dev", "raw_id": "dev-xxx"},
{"branch": "dev", "raw_id": "dev-yyy"},
{"branches": ["stable"], "raw_id": "stable-xxx"},
{"branches": ["stable"], "raw_id": "stable-yyy"},
{"branches": ["dev"], "raw_id": "dev-xxx"},
{"branches": ["dev"], "raw_id": "dev-yyy"},
],
}
headers = {"exmaple-header": "header-values"}

View file

@ -25,32 +25,28 @@ from rhodecode.lib.codeblocks import tokenize_string, split_token_stream, rollup
class TestTokenizeString(object):
python_code = """
import this
import this
var = 6
print("this")
"""
var = 6
print("this")
"""
def test_tokenize_as_python(self):
lexer = get_lexer_by_name("python")
tokens = list(tokenize_string(self.python_code, lexer))
expected_tokens = [
("w", "\n"),
("", " "),
("kn", "import"),
("", " "),
("w", " "),
("nn", "this"),
("w", "\n"),
("w", "\n"),
("", " "),
("n", "var"),
("", " "),
("o", "="),
("", " "),
("mi", "6"),
("w", "\n"),
("", " "),
("nb", "print"),
("p", "("),
("s2", '"'),
@ -58,8 +54,6 @@ class TestTokenizeString(object):
("s2", '"'),
("p", ")"),
("w", "\n"),
("w", "\n"),
("", " "),
]
assert tokens == expected_tokens
@ -68,7 +62,7 @@ class TestTokenizeString(object):
lexer = get_lexer_by_name("text")
tokens = list(tokenize_string(self.python_code, lexer))
assert tokens == [("", '\n import this\n\n var = 6\n print("this")\n\n ')]
assert tokens == [("", '\nimport this\n\nvar = 6\nprint("this")\n')]
class TestSplitTokenStream(object):

View file

@ -58,7 +58,7 @@ class TestBranches(BackendTestMixin):
branch="foobar",
)
assert "foobar" in self.repo.branches
assert foobar_tip.branch == "foobar"
assert foobar_tip.branches == ["foobar"]
@pytest.mark.backends("git", "hg")
def test_new_head(self):
@ -72,11 +72,11 @@ class TestBranches(BackendTestMixin):
parents=[tip],
)
self.imc.change(FileNode(b"docs/index.txt", content=b"Documentation\nand more...\n"))
assert foobar_tip.branch == "foobar"
assert foobar_tip.branches == ["foobar"]
newtip = self.imc.commit(
message="At foobar_tip branch",
author="joe <joe@rhodecode.com>",
branch=foobar_tip.branch,
branch=foobar_tip.branches[0],
parents=[foobar_tip],
)
@ -87,7 +87,7 @@ class TestBranches(BackendTestMixin):
parents=[tip, newtip],
)
assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
assert newest_tip.branches == [self.backend_class.DEFAULT_BRANCH_NAME]
@pytest.mark.backends("git", "hg")
def test_branch_with_slash_in_name(self):

View file

@ -45,7 +45,7 @@ class TestBaseChangeset(object):
class TestEmptyCommit(object):
def test_branch_without_alias_returns_none(self):
commit = EmptyCommit()
assert commit.branch is None
assert commit.branches == []
@pytest.mark.usefixtures("vcs_repository_support")
@ -78,7 +78,7 @@ class TestCommitsInNonEmptyRepo(BackendTestMixin):
branch="foobar",
)
assert "foobar" in self.repo.branches
assert foobar_tip.branch == "foobar"
assert foobar_tip.branches == ["foobar"]
# 'foobar' should be the only branch that contains the new commit
branch = list(self.repo.branches.values())
assert branch[0] != branch[1]
@ -95,11 +95,11 @@ class TestCommitsInNonEmptyRepo(BackendTestMixin):
parents=[tip],
)
self.imc.change(FileNode(b"docs/index.txt", content=b"Documentation\nand more...\n"))
assert foobar_tip.branch == "foobar"
assert foobar_tip.branches == ["foobar"]
newtip = self.imc.commit(
message="At foobar_tip branch",
author="joe <joe@rhodecode.com>",
branch=foobar_tip.branch,
branch=foobar_tip.branches[0],
parents=[foobar_tip],
)
@ -110,7 +110,7 @@ class TestCommitsInNonEmptyRepo(BackendTestMixin):
parents=[tip, newtip],
)
assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
assert newest_tip.branches == [self.backend_class.DEFAULT_BRANCH_NAME]
@pytest.mark.backends("git", "hg")
def test_get_commits_respects_branch_name(self):
@ -226,7 +226,8 @@ class TestCommits(BackendTestMixin):
tip = self.repo.get_commit()
# json.dumps(tip) uses .__json__() method
data = tip.__json__()
assert "branch" in data
assert "branches" in data
assert isinstance(data["branches"], list)
assert data["revision"]
def test_retrieve_tip(self):

View file

@ -555,20 +555,31 @@ TODO: To be written...
def test_merge_target_is_bookmark(self, vcsbackend_hg):
target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
source_repo = vcsbackend_hg.clone_repo(target_repo)
vcsbackend_hg.add_file(target_repo, "README_MERGE1", "Version 1")
vcsbackend_hg.add_file(source_repo, "README_MERGE2", "Version 2")
imc = source_repo.in_memory_commit
imc.add(FileNode(b"file_x", content=source_repo.name))
imc.commit(message="Automatic commit from repo merge test", author="Automatic <automatic@rhodecode.com>")
vcsbackend_hg.add_file(
source_repo,
"file_x",
content=source_repo.name,
msg="Automatic commit from repo merge test",
author="Automatic <automatic@rhodecode.com>",
)
target_commit = target_repo.get_commit()
source_commit = source_repo.get_commit()
default_branch = target_repo.DEFAULT_BRANCH_NAME
bookmark_name = "bookmark"
target_repo._update(default_branch)
target_repo.bookmark(bookmark_name)
target_ref = Reference("book", bookmark_name, target_commit.raw_id)
source_ref = Reference("branch", default_branch, source_commit.raw_id)
workspace_id = "test-merge"
repo_id = repo_id_generator(target_repo.path)
merge_response = target_repo.merge(
repo_id,
@ -601,18 +612,31 @@ TODO: To be written...
def test_merge_source_is_bookmark(self, vcsbackend_hg):
target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
source_repo = vcsbackend_hg.clone_repo(target_repo)
imc = source_repo.in_memory_commit
imc.add(FileNode(b"file_x", content=source_repo.name))
imc.commit(message="Automatic commit from repo merge test", author="Automatic <automatic@rhodecode.com>")
vcsbackend_hg.add_file(target_repo, "README_MERGE1", "Version 1")
vcsbackend_hg.add_file(source_repo, "README_MERGE2", "Version 2")
vcsbackend_hg.add_file(
source_repo,
"file_x",
content=source_repo.name,
msg="Automatic commit from repo merge test",
author="Automatic <automatic@rhodecode.com>",
)
target_commit = target_repo.get_commit()
source_commit = source_repo.get_commit()
default_branch = target_repo.DEFAULT_BRANCH_NAME
bookmark_name = "bookmark"
target_ref = Reference("branch", default_branch, target_commit.raw_id)
source_repo._update(default_branch)
source_repo.bookmark(bookmark_name)
source_repo.bookmark(bookmark_name, source_commit.raw_id)
target_ref = Reference("branch", default_branch, target_commit.raw_id)
source_ref = Reference("book", bookmark_name, source_commit.raw_id)
workspace_id = "test-merge"
repo_id = repo_id_generator(target_repo.path)
merge_response = target_repo.merge(
repo_id,
@ -631,8 +655,8 @@ TODO: To be written...
target_repo = backends.get_backend(vcsbackend_hg.alias)(target_repo.path)
target_commits = list(target_repo.get_commits())
commit_ids = [c.raw_id for c in target_commits]
assert source_ref.commit_id == commit_ids[-1]
assert target_ref.commit_id == commit_ids[-2]
assert source_ref.commit_id == commit_ids[-2]
assert target_ref.commit_id == commit_ids[-4]
def test_merge_target_has_multiple_heads(self, vcsbackend_hg):
target_repo = vcsbackend_hg.create_repo(number_of_commits=2)
@ -819,15 +843,15 @@ class TestMercurialCommit:
def test_branch_and_tags(self):
commit0 = self.repo.get_commit(commit_idx=0)
assert commit0.branch == "default"
assert commit0.branches == ["default"]
assert commit0.tags == []
commit10 = self.repo.get_commit(commit_idx=10)
assert commit10.branch == "default"
assert commit10.branches == ["default"]
assert commit10.tags == []
commit44 = self.repo.get_commit(commit_idx=44)
assert commit44.branch == "web"
assert commit44.branches == ["web"]
tip = self.repo.get_commit("tip")
assert "tip" in tip.tags
@ -1156,18 +1180,18 @@ class TestMercurialCommit:
def test_commit_message_is_unicode(self):
for cm in self.repo:
assert type(cm.message) == str
assert type(cm.message) is str
def test_commit_author_is_unicode(self):
for cm in self.repo:
assert type(cm.author) == str
assert type(cm.author) is str
def test_repo_files_content_type(self):
test_commit = self.repo.get_commit(commit_idx=100)
for node in test_commit.get_node(b"/"):
if node.is_file():
assert type(node.content) == bytes
assert type(node.str_content) == str
assert type(node.content) is bytes
assert type(node.str_content) is str
def test_wrong_path(self):
# There is 'setup.py' in the root dir but not there: