multicz 1.0.0__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {multicz-1.0.0 → multicz-1.2.0}/PKG-INFO +1 -1
- {multicz-1.0.0 → multicz-1.2.0}/pyproject.toml +1 -1
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/changelog/bucket.py +41 -5
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/changelog/debian.py +4 -2
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/changelog/markdown.py +13 -2
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/bump.py +1 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/presenters.py +2 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/config/models.py +8 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/writers/debian_changelog.py +2 -1
- {multicz-1.0.0 → multicz-1.2.0}/README.md +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/__main__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/changelog/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/_shared.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/artifacts.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/changed.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/changelog.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/check.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/config.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/explain.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/get.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/graph.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/init.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/plan.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/release_notes.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/state.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/status.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/commands/validate.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/cli/results.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/commits/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/commits/git.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/commits/parse.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/config/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/config/components.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/config/sources.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/_common.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/cargo.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/context.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/debian.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/go.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/gradle.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/helm.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/node.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/python.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/registry.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/discovery/relations.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/_base.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/_common.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/json.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/plain.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/properties.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/regex.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/toml.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/formats/yaml.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/planner/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/planner/build.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/planner/plan.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/planner/reasons.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/state/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/_base.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/_cycle.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/_git.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/bump_files.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/changelog.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/cycles.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/mirrors.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/overlap.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/state.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/validation/versions.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/writers/__init__.py +0 -0
- {multicz-1.0.0 → multicz-1.2.0}/src/multicz/writers/_base.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: multicz
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Multi-component versioning for monorepos: bump apps, charts, and images independently from conventional commits.
|
|
5
5
|
Keywords: semver,monorepo,helm,conventional-commits,release,versioning
|
|
6
6
|
Author: Chris
|
|
@@ -14,10 +14,10 @@ markers).
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from collections.abc import Iterable, Sequence
|
|
17
|
+
from collections.abc import Iterable, Mapping, Sequence
|
|
18
18
|
from dataclasses import dataclass, field
|
|
19
19
|
|
|
20
|
-
from ..commits import Commit
|
|
20
|
+
from ..commits import BumpRule, Commit
|
|
21
21
|
from ..config import ChangelogSection, _default_changelog_sections
|
|
22
22
|
|
|
23
23
|
|
|
@@ -51,6 +51,7 @@ def bucket_commits(
|
|
|
51
51
|
commits: Iterable[Commit],
|
|
52
52
|
*,
|
|
53
53
|
sections: Sequence[ChangelogSection] | None = None,
|
|
54
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
54
55
|
breaking_title: str = "Breaking changes",
|
|
55
56
|
other_title: str = "",
|
|
56
57
|
) -> BucketedCommits:
|
|
@@ -61,6 +62,13 @@ def bucket_commits(
|
|
|
61
62
|
breaking bucket (breaking commits then fall through to whichever
|
|
62
63
|
section claims their type), ``other_title=""`` drops unmatched
|
|
63
64
|
commits entirely.
|
|
65
|
+
|
|
66
|
+
``bump_rules`` (if passed) bridges the bump configuration with the
|
|
67
|
+
rendered sections. Any commit type with a non-``"none"`` rule is
|
|
68
|
+
considered "interesting": if no explicit section claims it, an
|
|
69
|
+
auto-bucket titled ``type.title()`` is created (e.g. ``docs:`` →
|
|
70
|
+
``"Docs"`` section). Auto-buckets render *after* the explicitly
|
|
71
|
+
declared sections, in alphabetical order for determinism.
|
|
64
72
|
"""
|
|
65
73
|
sections = list(sections) if sections is not None else _default_changelog_sections()
|
|
66
74
|
relevant = [c for c in commits if c.is_conventional]
|
|
@@ -80,12 +88,31 @@ def bucket_commits(
|
|
|
80
88
|
if items:
|
|
81
89
|
by_section[section.title] = items
|
|
82
90
|
|
|
91
|
+
section_claimed = {t.lower() for s in sections for t in s.types}
|
|
92
|
+
|
|
93
|
+
# Auto-buckets for types declared in bump_rules but not claimed by
|
|
94
|
+
# any explicit section. Sorted for stable output.
|
|
95
|
+
rule_claimed: set[str] = set()
|
|
96
|
+
if bump_rules:
|
|
97
|
+
rule_claimed = {
|
|
98
|
+
t.lower()
|
|
99
|
+
for t, kind in bump_rules.items()
|
|
100
|
+
if kind != "none"
|
|
101
|
+
}
|
|
102
|
+
for type_name in sorted(rule_claimed - section_claimed):
|
|
103
|
+
items = [
|
|
104
|
+
c for c in relevant
|
|
105
|
+
if id(c) not in breaking_set and c.type.lower() == type_name
|
|
106
|
+
]
|
|
107
|
+
if items:
|
|
108
|
+
by_section[type_name.title()] = items
|
|
109
|
+
|
|
83
110
|
leftovers: list[Commit] = []
|
|
84
111
|
if other_title:
|
|
85
|
-
|
|
112
|
+
all_claimed = section_claimed | rule_claimed
|
|
86
113
|
leftovers = [
|
|
87
114
|
c for c in relevant
|
|
88
|
-
if id(c) not in breaking_set and c.type.lower() not in
|
|
115
|
+
if id(c) not in breaking_set and c.type.lower() not in all_claimed
|
|
89
116
|
]
|
|
90
117
|
|
|
91
118
|
return BucketedCommits(
|
|
@@ -99,6 +126,7 @@ def filter_commits(
|
|
|
99
126
|
commits: Iterable[Commit],
|
|
100
127
|
*,
|
|
101
128
|
sections: Sequence[ChangelogSection] | None = None,
|
|
129
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
102
130
|
breaking_title: str = "Breaking changes",
|
|
103
131
|
other_title: str = "",
|
|
104
132
|
) -> list[Commit]:
|
|
@@ -108,9 +136,17 @@ def filter_commits(
|
|
|
108
136
|
list bullets in original commit order). Equivalent to "any commit
|
|
109
137
|
that ``bucket_commits`` would have placed somewhere", expressed as
|
|
110
138
|
a single list.
|
|
139
|
+
|
|
140
|
+
Same ``bump_rules`` semantics as :func:`bucket_commits`: a type
|
|
141
|
+
with a non-``"none"`` rule is kept even when no explicit section
|
|
142
|
+
claims it.
|
|
111
143
|
"""
|
|
112
144
|
sections = list(sections) if sections is not None else _default_changelog_sections()
|
|
113
145
|
section_types = {t.lower() for s in sections for t in s.types}
|
|
146
|
+
rule_types = {
|
|
147
|
+
t.lower() for t, kind in (bump_rules or {}).items() if kind != "none"
|
|
148
|
+
}
|
|
149
|
+
keep = section_types | rule_types
|
|
114
150
|
keep_breaking = bool(breaking_title)
|
|
115
151
|
keep_leftovers = bool(other_title)
|
|
116
152
|
return [
|
|
@@ -118,7 +154,7 @@ def filter_commits(
|
|
|
118
154
|
if c.is_conventional
|
|
119
155
|
and (
|
|
120
156
|
(keep_breaking and c.breaking)
|
|
121
|
-
or c.type.lower() in
|
|
157
|
+
or c.type.lower() in keep
|
|
122
158
|
or keep_leftovers
|
|
123
159
|
)
|
|
124
160
|
]
|
|
@@ -27,12 +27,12 @@ configured Debian revision when writing a new stanza.
|
|
|
27
27
|
from __future__ import annotations
|
|
28
28
|
|
|
29
29
|
import re
|
|
30
|
-
from collections.abc import Iterable, Sequence
|
|
30
|
+
from collections.abc import Iterable, Mapping, Sequence
|
|
31
31
|
from dataclasses import dataclass
|
|
32
32
|
from datetime import UTC, datetime
|
|
33
33
|
from email.utils import format_datetime
|
|
34
34
|
|
|
35
|
-
from ..commits import Commit
|
|
35
|
+
from ..commits import BumpRule, Commit
|
|
36
36
|
from ..config import ChangelogSection
|
|
37
37
|
from .bucket import filter_commits
|
|
38
38
|
|
|
@@ -195,6 +195,7 @@ def render_stanza(
|
|
|
195
195
|
maintainer: str = "Unknown <unknown@example.com>",
|
|
196
196
|
when: datetime | None = None,
|
|
197
197
|
sections: Sequence[ChangelogSection] | None = None,
|
|
198
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
198
199
|
breaking_title: str = "Breaking changes",
|
|
199
200
|
other_title: str = "",
|
|
200
201
|
) -> str:
|
|
@@ -222,6 +223,7 @@ def render_stanza(
|
|
|
222
223
|
filtered = filter_commits(
|
|
223
224
|
commits,
|
|
224
225
|
sections=sections,
|
|
226
|
+
bump_rules=bump_rules,
|
|
225
227
|
breaking_title=breaking_title,
|
|
226
228
|
other_title=other_title,
|
|
227
229
|
)
|
|
@@ -31,12 +31,12 @@ older release section.
|
|
|
31
31
|
from __future__ import annotations
|
|
32
32
|
|
|
33
33
|
import re
|
|
34
|
-
from collections.abc import Iterable, Sequence
|
|
34
|
+
from collections.abc import Iterable, Mapping, Sequence
|
|
35
35
|
from dataclasses import dataclass
|
|
36
36
|
from datetime import date
|
|
37
37
|
from pathlib import Path
|
|
38
38
|
|
|
39
|
-
from ..commits import Commit
|
|
39
|
+
from ..commits import BumpRule, Commit
|
|
40
40
|
from ..config import ChangelogSection, _default_changelog_sections
|
|
41
41
|
from .bucket import bucket_commits
|
|
42
42
|
|
|
@@ -75,6 +75,7 @@ def render_body(
|
|
|
75
75
|
commits: Iterable[Commit],
|
|
76
76
|
*,
|
|
77
77
|
sections: Sequence[ChangelogSection] | None = None,
|
|
78
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
78
79
|
breaking_title: str = "Breaking changes",
|
|
79
80
|
other_title: str = "",
|
|
80
81
|
cascades: Sequence[CascadeEntry] | None = None,
|
|
@@ -87,6 +88,11 @@ def render_body(
|
|
|
87
88
|
commits then fall through to whichever section claims their type).
|
|
88
89
|
Empty string ``other_title`` drops unmatched conventional commits.
|
|
89
90
|
|
|
91
|
+
``bump_rules`` (when passed) ties the rendered sections to the bump
|
|
92
|
+
configuration: a type with a non-``"none"`` rule is included even
|
|
93
|
+
if no explicit section claims it (auto-bucketed under
|
|
94
|
+
``type.title()``). See :func:`bucket_commits`.
|
|
95
|
+
|
|
90
96
|
``cascades`` lists upstream bumps that pulled this component along
|
|
91
97
|
(mirror writes, trigger edges). When present and ``cascade_title``
|
|
92
98
|
is non-empty, they render as a dedicated H3 section; this also
|
|
@@ -97,6 +103,7 @@ def render_body(
|
|
|
97
103
|
bucketed = bucket_commits(
|
|
98
104
|
commits,
|
|
99
105
|
sections=sections,
|
|
106
|
+
bump_rules=bump_rules,
|
|
100
107
|
breaking_title=breaking_title,
|
|
101
108
|
other_title=other_title,
|
|
102
109
|
)
|
|
@@ -173,6 +180,7 @@ def render_section(
|
|
|
173
180
|
*,
|
|
174
181
|
today: date | None = None,
|
|
175
182
|
sections: Sequence[ChangelogSection] | None = None,
|
|
183
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
176
184
|
breaking_title: str = "Breaking changes",
|
|
177
185
|
other_title: str = "",
|
|
178
186
|
cascades: Sequence[CascadeEntry] | None = None,
|
|
@@ -184,6 +192,7 @@ def render_section(
|
|
|
184
192
|
body = render_body(
|
|
185
193
|
commits,
|
|
186
194
|
sections=sections,
|
|
195
|
+
bump_rules=bump_rules,
|
|
187
196
|
breaking_title=breaking_title,
|
|
188
197
|
other_title=other_title,
|
|
189
198
|
cascades=cascades,
|
|
@@ -236,6 +245,7 @@ def update_changelog_file(
|
|
|
236
245
|
*,
|
|
237
246
|
today: date | None = None,
|
|
238
247
|
sections: Sequence[ChangelogSection] | None = None,
|
|
248
|
+
bump_rules: Mapping[str, BumpRule] | None = None,
|
|
239
249
|
breaking_title: str = "Breaking changes",
|
|
240
250
|
other_title: str = "",
|
|
241
251
|
drop_prereleases: bool = False,
|
|
@@ -254,6 +264,7 @@ def update_changelog_file(
|
|
|
254
264
|
commits,
|
|
255
265
|
today=today,
|
|
256
266
|
sections=sections,
|
|
267
|
+
bump_rules=bump_rules,
|
|
257
268
|
breaking_title=breaking_title,
|
|
258
269
|
other_title=other_title,
|
|
259
270
|
cascades=cascades,
|
|
@@ -274,6 +274,7 @@ def bump(
|
|
|
274
274
|
new_version,
|
|
275
275
|
relevant,
|
|
276
276
|
sections=config.project.changelog_sections,
|
|
277
|
+
bump_rules=config.bump_rules_for(planned.component),
|
|
277
278
|
breaking_title=config.project.breaking_section_title,
|
|
278
279
|
other_title=config.project.other_section_title,
|
|
279
280
|
drop_prereleases=is_final and strategy == "promote",
|
|
@@ -449,6 +449,7 @@ def render_release_notes(
|
|
|
449
449
|
body = render_body(
|
|
450
450
|
list(s.commits),
|
|
451
451
|
sections=config.project.changelog_sections,
|
|
452
|
+
bump_rules=config.bump_rules_for(s.component),
|
|
452
453
|
breaking_title=config.project.breaking_section_title,
|
|
453
454
|
other_title=config.project.other_section_title,
|
|
454
455
|
cascades=list(s.cascades) if s.cascades else None,
|
|
@@ -490,6 +491,7 @@ def render_changelog(
|
|
|
490
491
|
body = render_body(
|
|
491
492
|
list(entry.relevant),
|
|
492
493
|
sections=config.project.changelog_sections,
|
|
494
|
+
bump_rules=config.bump_rules_for(entry.component),
|
|
493
495
|
breaking_title=config.project.breaking_section_title,
|
|
494
496
|
other_title=config.project.other_section_title,
|
|
495
497
|
)
|
|
@@ -115,6 +115,14 @@ class DebianChangelogWriter(BaseModel):
|
|
|
115
115
|
maintainer: str | None = None # falls back to debian/control then git config
|
|
116
116
|
debian_revision: int = 1
|
|
117
117
|
epoch: int | None = None
|
|
118
|
+
# Debian package name written into each new stanza header. Defaults
|
|
119
|
+
# to the multicz component name when unset. Override when the
|
|
120
|
+
# component name (typically short - "api", "worker") differs from
|
|
121
|
+
# the Debian binary package name (typically prefixed -
|
|
122
|
+
# "shomer-api"); ``dpkg-source`` errors out otherwise because the
|
|
123
|
+
# changelog's package name must match ``debian/control``'s
|
|
124
|
+
# ``Source:`` field.
|
|
125
|
+
package: str | None = None
|
|
118
126
|
|
|
119
127
|
|
|
120
128
|
# Discriminated union of all writer types. Add new writer schemas here
|
|
@@ -67,13 +67,14 @@ class DebianChangelogImpl:
|
|
|
67
67
|
)
|
|
68
68
|
maintainer = _resolve_maintainer(ctx.repo, writer.maintainer)
|
|
69
69
|
stanza = render_stanza(
|
|
70
|
-
package=ctx.component_name,
|
|
70
|
+
package=writer.package or ctx.component_name,
|
|
71
71
|
version=debian_version,
|
|
72
72
|
distribution=writer.distribution,
|
|
73
73
|
urgency=writer.urgency,
|
|
74
74
|
commits=ctx.relevant_commits,
|
|
75
75
|
maintainer=maintainer,
|
|
76
76
|
sections=config.project.changelog_sections,
|
|
77
|
+
bump_rules=config.bump_rules_for(ctx.component_name),
|
|
77
78
|
breaking_title=config.project.breaking_section_title,
|
|
78
79
|
other_title=config.project.other_section_title,
|
|
79
80
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|