moat-src 0.8.1__tar.gz → 0.8.3__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.
Files changed (25) hide show
  1. {moat_src-0.8.1/moat_src.egg-info → moat_src-0.8.3}/PKG-INFO +1 -1
  2. {moat_src-0.8.1 → moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages}/moat/src/_main.py +152 -163
  3. moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages/moat/src/_templates/moat/__init__.py +3 -0
  4. moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages/moat/src/_templates/pyproject.default.yaml +146 -0
  5. moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages/moat/src/_templates/pyproject.forced.yaml +77 -0
  6. moat_src-0.8.3/moat/src/__init__.py +0 -0
  7. moat_src-0.8.3/moat/src/_main.py +1113 -0
  8. moat_src-0.8.3/moat/src/_templates/moat/__init__.py +3 -0
  9. moat_src-0.8.3/moat/src/_templates/pyproject.default.yaml +146 -0
  10. moat_src-0.8.3/moat/src/_templates/pyproject.forced.yaml +77 -0
  11. moat_src-0.8.3/moat/src/inspect.py +65 -0
  12. moat_src-0.8.3/moat/src/test.py +89 -0
  13. {moat_src-0.8.1 → moat_src-0.8.3/moat_src.egg-info}/PKG-INFO +1 -1
  14. moat_src-0.8.3/moat_src.egg-info/SOURCES.txt +21 -0
  15. moat_src-0.8.3/moat_src.egg-info/top_level.txt +4 -0
  16. {moat_src-0.8.1 → moat_src-0.8.3}/pyproject.toml +3 -2
  17. moat_src-0.8.1/moat_src.egg-info/SOURCES.txt +0 -11
  18. moat_src-0.8.1/moat_src.egg-info/top_level.txt +0 -1
  19. {moat_src-0.8.1 → moat_src-0.8.3}/LICENSE.txt +0 -0
  20. {moat_src-0.8.1 → moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages}/moat/src/__init__.py +0 -0
  21. {moat_src-0.8.1 → moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages}/moat/src/inspect.py +0 -0
  22. {moat_src-0.8.1 → moat_src-0.8.3/debian/moat-src/usr/lib/python3/dist-packages}/moat/src/test.py +0 -0
  23. {moat_src-0.8.1 → moat_src-0.8.3}/moat_src.egg-info/dependency_links.txt +0 -0
  24. {moat_src-0.8.1 → moat_src-0.8.3}/moat_src.egg-info/requires.txt +0 -0
  25. {moat_src-0.8.1 → moat_src-0.8.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moat-src
3
- Version: 0.8.1
3
+ Version: 0.8.3
4
4
  Summary: Tools for managing the MoaT sources
5
5
  Author-email: Matthias Urlichs <matthias@urlichs.de>
6
6
  Project-URL: homepage, https://m-o-a-t.org
@@ -67,10 +67,9 @@ class ChangedError(RuntimeError):
67
67
  return f"{s} changed between {tag.name} and {head}"
68
68
 
69
69
  class _Common:
70
- _last_tag:str = None
71
70
 
72
71
  def next_tag(self,major:bool=False,minor:bool=False):
73
- tag = self.last_tag()[0]
72
+ tag = self.last_tag
74
73
  try:
75
74
  n = [ int(x) for x in tag.split('.') ]
76
75
  if len(n) != 3:
@@ -94,7 +93,7 @@ class Package(_Common):
94
93
  path:Path = field(init=False,repr=False)
95
94
  files:set(Path) = field(init=False,factory=set,repr=False)
96
95
  subs:dict[str,Package] = field(factory=dict,init=False,repr=False)
97
- hidden:bool = field(init=False)
96
+ hidden:bool = field(init=False,repr=False)
98
97
 
99
98
  def __init__(self, repo, name):
100
99
  self.__attrs_init__(repo,name)
@@ -112,6 +111,33 @@ class Package(_Common):
112
111
  def __hash__(self):
113
112
  return hash(self.name)
114
113
 
114
+ @property
115
+ def vers(self):
116
+ v = self._repo.versions[self.dash]
117
+ if not isinstance(v,dict):
118
+ tag,commit = v
119
+ v = attrdict(
120
+ tag=tag,
121
+ pkg=1,
122
+ rev=commit,
123
+ )
124
+ self._repo.versions[self.dash] = v
125
+ return v
126
+
127
+ @vers.setter
128
+ def vers(self,d):
129
+ v = self.vers
130
+ v.update(d)
131
+ return v
132
+
133
+ @property
134
+ def last_tag(self):
135
+ return self.vers.tag
136
+
137
+ @property
138
+ def last_commit(self):
139
+ return self.vers.rev
140
+
115
141
  @property
116
142
  def mdash(self):
117
143
  d=dash(self.name)
@@ -155,27 +181,15 @@ class Package(_Common):
155
181
  if not licd.exists():
156
182
  copyfile("LICENSE.txt", licd)
157
183
 
158
- def last_tag(self, unchanged:bool=False) -> Tag|None:
159
- """
160
- Return the most-recent tag for this subrepo
161
- """
162
- tag,commit = self._repo.versions[self.dash]
163
- if unchanged and self.has_changes(commit):
164
- raise ChangedError(subsys,t,ref)
165
- return tag,commit
166
-
167
- def has_changes(self, tag:Commit=None) -> bool:
184
+ def has_changes(self, main:bool|None=None) -> bool:
168
185
  """
169
- Test whether the given subsystem (or any subsystem)
170
- changed between the head and the @tag commit
186
+ Test whether the given subsystem changed
187
+ between the head and the @tag commit
171
188
  """
172
- if tag is None:
173
- tag,commit = self.last_tag()
174
- else:
175
- commit = tag
189
+ commit = self.last_commit
176
190
  head = self._repo.head.commit
177
- for d in head.diff(commit):
178
- if self._repo.repo_for(d.a_path) != self.name and self._repo.repo_for(d.b_path) != self.name:
191
+ for d in head.diff(self.last_commit):
192
+ if self._repo.repo_for(d.a_path, main) != self.name and self._repo.repo_for(d.b_path, main) != self.name:
179
193
  continue
180
194
  return True
181
195
  return False
@@ -202,7 +216,7 @@ class Repo(git.Repo,_Common):
202
216
  mi = p.parts.index("moat")
203
217
  self.moat_name = "-".join(p.parts[mi:])
204
218
  with open("versions.yaml") as f:
205
- self.versions = yload(f)
219
+ self.versions = yload(f, attr=True)
206
220
 
207
221
  def write_tags(self):
208
222
  with open("versions.yaml","w") as f:
@@ -210,24 +224,30 @@ class Repo(git.Repo,_Common):
210
224
  self.index.add("versions.yaml")
211
225
 
212
226
 
213
- def last_tag(self, unchanged:bool=False) -> Tag|None:
227
+ @property
228
+ def last_tag(self) -> Tag|None:
214
229
  """
215
230
  Return the most-recent tag for this repo
216
231
  """
217
232
  if self._last_tag is not None:
218
- return self._last_tag,self._last_tag
233
+ return self._last_tag
234
+
219
235
  for c in self._repo.commits(self.head.commit):
220
236
  t = self.tagged(c)
221
237
  if t is None:
222
238
  continue
223
239
 
224
240
  self._last_tag = t
225
- if unchanged and self.has_changes(c):
226
- raise ChangedError(subsys,t)
227
- return t,t
241
+ return t
228
242
 
229
243
  raise ValueError(f"No tags found")
230
244
 
245
+ @property
246
+ def last_commit(self) -> str:
247
+ t = self.last_tag
248
+ c = self.tags[t].commit
249
+ return c.hexsha
250
+
231
251
  def part(self, name):
232
252
  return self._repos[dash(name)]
233
253
 
@@ -267,29 +287,31 @@ class Repo(git.Repo,_Common):
267
287
 
268
288
  self._repos["main"].populate(Path("moat"))
269
289
 
270
- def repo_for(self, path:Path|str) -> str:
290
+ def repo_for(self, path:Path|str, main:bool|None) -> str:
271
291
  """
272
292
  Given a file path, returns the subrepo in question
273
293
  """
274
- name = "moat"
275
294
  sc = self._repos["main"]
276
295
  path=Path(path)
277
- try:
278
- if path.parts[0] == "packaging":
279
- return path.parts[1].replace("-",".")
280
- except KeyError:
281
- return name
282
296
 
283
- if path.parts[0] != "moat":
297
+ if main is not False and path.parts[0] == "moat":
298
+ name = "moat"
299
+ for p in path.parts[1:]:
300
+ if p in sc.subs:
301
+ name += "."+p
302
+ sc = sc.subs[p]
303
+ else:
304
+ break
284
305
  return name
285
306
 
286
- for p in path.parts[1:]:
287
- if p in sc.subs:
288
- name += "."+p
289
- sc = sc.subs[p]
290
- else:
291
- break
292
- return name
307
+ if main is not True and path.parts[0] == "packaging":
308
+ try:
309
+ return undash(path.parts[1])
310
+ except IndexError:
311
+ return None
312
+
313
+ return None
314
+
293
315
 
294
316
  def commits(self, ref=None):
295
317
  """Iterate over topo sort of commits following @ref, or HEAD.
@@ -312,16 +334,16 @@ class Repo(git.Repo,_Common):
312
334
  yield ref
313
335
  work.extend(ref.parents)
314
336
 
315
- def has_changes(self, tag:Tag=None) -> bool:
337
+ def has_changes(self, main:bool|None=None) -> bool:
316
338
  """
317
339
  Test whether any subsystem changed since the "tagged" commit
318
340
 
319
341
  """
320
342
  if tag is None:
321
- tag,commit = self.last_tag()
343
+ tag = self.last_tag
322
344
  head = self._repo.head.commit
323
345
  for d in head.diff(tag):
324
- if self.repo_for(d.a_path) == "moat" and self.repo_for(d.b_path) == "moat":
346
+ if self.repo_for(d.a_path, main) == "moat" and self.repo_for(d.b_path, main) == "moat":
325
347
  continue
326
348
  return True
327
349
  return False
@@ -692,49 +714,23 @@ def path_():
692
714
 
693
715
 
694
716
  @cli.command()
695
- @click.option("-s", "--show", is_flag=True, help="Show all tags")
696
- @click.option("-r", "--run", is_flag=True, help="Update all stale tags")
697
- def tags(show,run):
717
+ def tags():
718
+ """
719
+ List all tags
720
+ """
698
721
  repo = Repo(None)
699
722
 
700
- if show:
701
- if run:
702
- raise click.UsageError("Can't display and change the tag at the same time!")
703
-
704
- for r in repo.parts:
705
- try:
706
- tag,commit = r.last_tag()
707
- except ValueError:
708
- print(f"{r.dash} -")
709
- continue
710
- if r.has_changes(commit):
711
- print(f"{r.dash} {tag} STALE")
712
- else:
713
- print(f"{r.dash} {tag}")
714
- return
715
-
716
- if repo.is_dirty(index=True, working_tree=True, untracked_files=True, submodules=False):
717
- print("Repo is dirty. Not tagging globally.", file=sys.stderr)
718
- return
719
-
720
- changed=False
721
723
  for r in repo.parts:
722
- tag,commit = r.last_tag()
723
- if not r.has_changes(commit):
724
- print(repo.dash,tag,"UNCHANGED")
725
- continue
726
-
727
- tag = r.next_tag()
728
- print(repo.dash,tag)
729
- if not run:
724
+ try:
725
+ tag = r.last_tag
726
+ except KeyError:
730
727
  continue
731
-
732
- repo.versions[r.dash] = (tag,repo.head.commit.hexsha[:9])
733
- changed=True
734
-
735
- if changed:
736
- repo.write_tags()
737
-
728
+ if r.has_changes(True):
729
+ print(f"{r.dash} {tag} STALE")
730
+ elif r.has_changes(True):
731
+ print(f"{r.dash} {tag} REBUILD")
732
+ else:
733
+ print(f"{r.dash} {tag}")
738
734
 
739
735
  @cli.command()
740
736
  @click.option("-r", "--run", is_flag=True, help="actually do the tagging")
@@ -744,18 +740,27 @@ def tags(show,run):
744
740
  @click.option("-v", "--tag", "force", type=str, help="Use this explicit tag value")
745
741
  @click.option("-q", "--query","--show","show", is_flag=True, help="Show the latest tag")
746
742
  @click.option("-f", "--force","FORCE", is_flag=True, help="replace an existing tag")
747
- def tag(run,minor,major,subtree,force,FORCE,show):
743
+ @click.option("-b", "--build", is_flag=True, help="set/increment the build number")
744
+ def tag(run,minor,major,subtree,force,FORCE,show,build):
748
745
  """
749
746
  Tag the repository (or a subtree).
747
+
748
+ MoaT versions are of the form ``a.b.c``. Binaries also have a build
749
+ number. This command auto-increments ``c`` and sets the build to ``1``,
750
+ except when you use ``-M|-m|-b``.
750
751
  """
751
752
  if minor and major:
752
753
  raise click.UsageError("Can't change both minor and major!")
753
754
  if force and (minor or major):
754
755
  raise click.UsageError("Can't use an explicit tag with changing minor or major!")
755
756
  if FORCE and (minor or major):
756
- raise click.UsageError("Can't use an explicit tag with changing minor or major!")
757
+ raise click.UsageError("Can't reuse a tag and also change minor or major!")
758
+ if (build or force) and (minor or major or (build and force)):
759
+ raise click.UsageError("Can't update both build and tag!")
757
760
  if show and (run or force or minor or major):
758
761
  raise click.UsageError("Can't display and change the tag at the same time!")
762
+ if build and not subtree:
763
+ raise click.UsageError("The main release number doesn't have a build")
759
764
 
760
765
  repo = Repo(None)
761
766
 
@@ -765,8 +770,8 @@ def tag(run,minor,major,subtree,force,FORCE,show):
765
770
  r = repo
766
771
 
767
772
  if show:
768
- tag,commit = r.last_tag()
769
- if r.has_changes(commit):
773
+ tag = r.last_tag
774
+ if r.has_changes():
770
775
  print(f"{tag} STALE")
771
776
  else:
772
777
  print(tag)
@@ -774,14 +779,23 @@ def tag(run,minor,major,subtree,force,FORCE,show):
774
779
 
775
780
  if force:
776
781
  tag = force
777
- elif FORCE:
778
- tag,_ = r.last_tag()
782
+ elif FORCE or build:
783
+ tag = r.last_tag
779
784
  else:
780
785
  tag = r.next_tag(major,minor)
781
786
 
782
787
  if run or subtree:
783
788
  if subtree:
784
- repo.versions[r.dash] = (tag,repo.head.commit.hexsha[:9])
789
+ sb = repo.part(r.dash)
790
+ if build:
791
+ sb.vers.pkg += 1
792
+ sb.vers.rev=repo.head.commit.hexsha
793
+ else:
794
+ sb.vers = attrdict(
795
+ tag=tag,
796
+ pkg=1,
797
+ rev=repo.head.commit.hexsha,
798
+ )
785
799
  repo.write_tags()
786
800
  else:
787
801
  git.TagReference.create(repo,tag, force=FORCE)
@@ -790,58 +804,6 @@ def tag(run,minor,major,subtree,force,FORCE,show):
790
804
  print(f"{tag} DRY_RUN")
791
805
 
792
806
 
793
- @cli.command()
794
- @click.option("-P", "--no-pypi", is_flag=True, help="don't push to PyPi")
795
- @click.option("-D", "--no-deb", is_flag=True, help="don't debianize")
796
- @click.option("-d", "--deb", type=str, help="Debian archive to push to (from dput.cfg)")
797
- @click.option("-o", "--only", type=str, multiple=True, help="affect only this package")
798
- @click.option("-s", "--skip", type=str, multiple=True, help="skip this package")
799
- async def publish(no_pypi, no_deb, skip, only, deb):
800
- """
801
- Publish modules to PyPi and/or Debian.
802
-
803
- MoaT modules can be given as shorthand, i.e. with dashes and excluding
804
- the "moat-" prefix.
805
- """
806
- repo = Repo(None)
807
- if only and skip:
808
- raise click.UsageError("You can't both include and exclude packages.")
809
-
810
- if only:
811
- repos = (repo.subrepo(x) for x in only)
812
- else:
813
- s = set()
814
- for sk in skip:
815
- s += set(sk.split(","))
816
- repos = (x for x in repo.parts if dash(x.name) not in sk)
817
-
818
- deb_args = "-b -us -uc".split()
819
-
820
- for r in repos:
821
- t,c = r.last_tag
822
- if r.has_changes(c):
823
- print(f"Error: changes in {r.name} since tag {t.name}")
824
- continue
825
-
826
- print(f"Processing {r.name}, tag: {t.name}")
827
- r.copy()
828
- rd=PACK/r.dash
829
-
830
- if not no_deb:
831
- p = rd / "debian"
832
- if not p.is_dir():
833
- continue
834
- subprocess.run(["debuild"] + deb_args, cwd=rd, check=True)
835
-
836
- if not no_pypi:
837
- for r in repos:
838
- p = Path(r.working_dir) / "pyproject.toml"
839
- if not p.is_file():
840
- continue
841
- print(r.working_dir)
842
- subprocess.run(["make", "pypi"], cwd=r.working_dir, check=True)
843
-
844
-
845
807
  @cli.command(epilog="""
846
808
  The default for building Debian packages is '--no-sign --build=binary'.
847
809
  '--no-sign' is dropped when you use '--deb'.
@@ -865,6 +827,7 @@ it is dropped when you use '--dput'.
865
827
  @click.option("-m", "--minor", is_flag=True, help="create a new minor version")
866
828
  @click.option("-M", "--major", is_flag=True, help="create a new major version")
867
829
  @click.option("-t", "--tag", "forcetag", type=str, help="Use this explicit tag value")
830
+ @click.option("-a", "--auto-tag", "autotag", is_flag=True, help="Auto-retag updated packages")
868
831
  @click.option(
869
832
  "-v",
870
833
  "--version",
@@ -873,7 +836,7 @@ it is dropped when you use '--dput'.
873
836
  help="Update external dependency",
874
837
  )
875
838
  @click.argument("parts", nargs=-1)
876
- async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts, pytest_opts, deb_opts, run, version, no_version, no_deb, skip_, major,minor,forcetag):
839
+ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts, pytest_opts, deb_opts, run, version, no_version, no_deb, skip_, major,minor,forcetag,autotag):
877
840
  """
878
841
  Rebuild all modified packages.
879
842
  """
@@ -891,6 +854,8 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
891
854
  print("Warning: not updating moat versions in pyproject files", file=sys.stderr)
892
855
  if minor and major:
893
856
  raise click.UsageError("Can't change both minor and major!")
857
+ if autotag and no_tag:
858
+ raise click.UsageError("Can't change tags without verifying them!")
894
859
  if forcetag and (minor or major):
895
860
  raise click.UsageError("Can't use an explicit tag with changing minor or major!")
896
861
 
@@ -927,11 +892,23 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
927
892
  return
928
893
 
929
894
  # Step 1: check for changed files since last tagging
930
- if not no_tag:
895
+ if autotag:
896
+ for r in repos:
897
+ if r.has_changes(True):
898
+ r.vers = attrdict(
899
+ tag=r.next_tag(),
900
+ pkg=1,
901
+ rev=repo.head.commit.hexsha,
902
+ )
903
+ elif r.has_changes(False):
904
+ r.vers.pkg += 1
905
+ r.vers.rev=repo.head.commit.hexsha
906
+
907
+ elif not no_tag:
931
908
  err = set()
932
909
  for r in repos:
933
910
  try:
934
- tag,commit = r.last_tag()
911
+ tag = r.last_tag
935
912
  except KeyError:
936
913
  rd = PACK/r.dash
937
914
  p = rd / "pyproject.toml"
@@ -939,7 +916,7 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
939
916
  continue
940
917
  raise
941
918
  tags[r.mdash] = tag
942
- if r.has_changes(commit):
919
+ if r.has_changes():
943
920
  err.add(r.dash)
944
921
  if err:
945
922
  if not run:
@@ -975,7 +952,7 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
975
952
  continue
976
953
  with p.open("r") as f:
977
954
  pr = tomlkit.load(f)
978
- pr["project"]["version"] = r.last_tag()[0]
955
+ pr["project"]["version"] = r.last_tag
979
956
 
980
957
  if not no_version:
981
958
  try:
@@ -1012,9 +989,9 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1012
989
  try:
1013
990
  res = subprocess.run(["dpkg-parsechangelog","-l","debian/changelog","-S","version"], cwd=rd, check=True, stdout=subprocess.PIPE)
1014
991
  tag = res.stdout.strip().decode("utf-8").rsplit("-",1)[0]
1015
- ltag = r.last_tag()[0]
992
+ ltag = r.last_tag
1016
993
  if tag != ltag:
1017
- subprocess.run(["debchange", "--distribution","unstable", "--newversion",ltag+"-1",f"New release for {forcetag}"] , cwd=rd, check=True)
994
+ subprocess.run(["debchange", "--distribution","unstable", "--newversion",f"{ltag}-{r.vers.rev}",f"New release for {forcetag}"] , cwd=rd, check=True)
1018
995
  repo.index.add(p/"changelog")
1019
996
 
1020
997
  if debversion.get(r.dash,"") != ltag:
@@ -1035,7 +1012,7 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1035
1012
  p = rd / "pyproject.toml"
1036
1013
  if not p.is_file():
1037
1014
  continue
1038
- tag = r.last_tag()[0]
1015
+ tag = r.last_tag
1039
1016
  name = r.dash
1040
1017
  if name.startswith("ext-"):
1041
1018
  name=name[4:]
@@ -1045,7 +1022,6 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1045
1022
  targz = rd/"dist"/f"{r.under}-{tag}.tar.gz"
1046
1023
  done = rd/"dist"/f"{r.under}-{tag}.done"
1047
1024
  if targz.is_file():
1048
- print(f"{name}: Source package exists.")
1049
1025
  if not done.exists():
1050
1026
  up.add(r)
1051
1027
  else:
@@ -1053,6 +1029,8 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1053
1029
  subprocess.run(["python3", "-mbuild", "-snw"], cwd=rd, check=True)
1054
1030
  except subprocess.CalledProcessError:
1055
1031
  err.add(r.name)
1032
+ else:
1033
+ up.add(r)
1056
1034
  if err:
1057
1035
  if not run:
1058
1036
  print("*** Build errors:", file=sys.stderr)
@@ -1066,21 +1044,21 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1066
1044
  # Step 6: upload PyPI package
1067
1045
  if run:
1068
1046
  err=set()
1069
- for p in up:
1047
+ for r in up:
1070
1048
  rd=PACK/r.dash
1071
1049
  p = rd / "pyproject.toml"
1072
1050
  if not p.is_file():
1073
1051
  continue
1074
- tag = r.last_tag()[0]
1052
+ tag = r.last_tag
1075
1053
  name = r.dash
1076
1054
  if name.startswith("ext-"):
1077
1055
  name=name[4:]
1078
1056
  else:
1079
1057
  name="moat-"+r.dash
1080
- targz = Path("dist")/f"{name}-{tag}.tar.gz"
1081
- whl = Path("dist")/f"{name}-{tag}-py3-none-any.whl"
1058
+ targz = Path("dist")/f"{r.under}-{tag}.tar.gz"
1059
+ whl = Path("dist")/f"{r.under}-{tag}-py3-none-any.whl"
1082
1060
  try:
1083
- subprocess.run(["twine", "upload", str(targz), str(whl)], cwd=rd, check=True)
1061
+ res = subprocess.run(["twine", "upload", str(targz), str(whl)], cwd=rd, check=True)
1084
1062
  except subprocess.CalledProcessError:
1085
1063
  err.add(r.name)
1086
1064
  else:
@@ -1098,12 +1076,19 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1098
1076
  if not dput_opts:
1099
1077
  dput_opts = ["-u","ext"]
1100
1078
  for r in repos:
1101
- ltag = r.last_tag()[0]
1102
- changes = PACK/f"{r.mdash}_{ltag}-1_{ARCH}.changes"
1079
+ ltag = r.last_tag
1080
+ if not (PACK/r.dash/"debian").is_dir():
1081
+ continue
1082
+ changes = PACK/f"{r.mdash}_{ltag}-{r.vers.rev}_{ARCH}.changes"
1083
+ done = PACK/f"{r.mdash}_{ltag}-{r.vers.rev}_{ARCH}.done"
1084
+ if done.exists():
1085
+ continue
1103
1086
  try:
1104
- subprocess.run(["dput", *dput_opts, str(changes)], cwd=PACK, check=True)
1087
+ subprocess.run(["dput", *dput_opts, str(changes)], check=True)
1105
1088
  except subprocess.CalledProcessError:
1106
1089
  err.add(r.name)
1090
+ else:
1091
+ done.touch()
1107
1092
  if err:
1108
1093
  print("Upload errors:", file=sys.stderr)
1109
1094
  print(*err, file=sys.stderr)
@@ -1111,10 +1096,14 @@ async def build(no_commit, no_dirty, no_test, no_tag, no_pypi, parts, dput_opts,
1111
1096
  return
1112
1097
 
1113
1098
  # Step 8: commit the result
1114
- if run and not no_commit:
1099
+ if run:
1100
+ for r in repos:
1101
+ r.vers.rev = repo.head.commit.hexsha
1115
1102
  repo.write_tags()
1116
- repo.index.commit(f"Build version {forcetag}")
1117
- git.TagReference.create(repo, forcetag)
1103
+
1104
+ if not no_commit:
1105
+ repo.index.commit(f"Build version {forcetag}")
1106
+ git.TagReference.create(repo, forcetag)
1118
1107
 
1119
1108
 
1120
1109
  add_repr(tomlkit.items.String)
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)