|
27 | 27 | # Ideas stolen from Mailman's release script, Lib/tokens.py and welease
|
28 | 28 |
|
29 | 29 |
|
| 30 | +class Tag: |
| 31 | + def __init__(self, tag_name): |
| 32 | + # if tag is ".", use current directory name as tag |
| 33 | + # e.g. if current directory name is "3.4.6", |
| 34 | + # "release.py --bump 3.4.6" and "release.py --bump ." are the same |
| 35 | + if tag_name == ".": |
| 36 | + tag_name = os.path.basename(os.getcwd()) |
| 37 | + result = tag_cre.match(tag_name) |
| 38 | + if result is None: |
| 39 | + error(f"tag {tag_name} is not valid") |
| 40 | + data = list(result.groups()) |
| 41 | + if data[3] is None: |
| 42 | + # A final release. |
| 43 | + self.is_final = True |
| 44 | + data[3] = "f" |
| 45 | + else: |
| 46 | + self.is_final = False |
| 47 | + # For everything else, None means 0. |
| 48 | + for i, thing in enumerate(data): |
| 49 | + if thing is None: |
| 50 | + data[i] = 0 |
| 51 | + self.major = int(data[0]) |
| 52 | + self.minor = int(data[1]) |
| 53 | + self.patch = int(data[2]) |
| 54 | + self.level = data[3] |
| 55 | + self.serial = int(data[4]) |
| 56 | + # This has the effect of normalizing the version. |
| 57 | + self.text = self.normalized() |
| 58 | + if self.level != "f": |
| 59 | + self.text += self.level + str(self.serial) |
| 60 | + self.basic_version = f"{self.major}.{self.minor}" |
| 61 | + |
| 62 | + def __str__(self): |
| 63 | + return self.text |
| 64 | + |
| 65 | + def normalized(self): |
| 66 | + return f"{self.major}.{self.minor}.{self.patch}" |
| 67 | + |
| 68 | + @property |
| 69 | + def branch(self): |
| 70 | + return "main" if self.is_alpha_release else f"{self.major}.{self.minor}" |
| 71 | + |
| 72 | + @property |
| 73 | + def is_alpha_release(self): |
| 74 | + return self.level == "a" |
| 75 | + |
| 76 | + @property |
| 77 | + def is_release_candidate(self): |
| 78 | + return self.level == "rc" |
| 79 | + |
| 80 | + @property |
| 81 | + def is_feature_freeze_release(self): |
| 82 | + return self.level == "b" and self.serial == 1 |
| 83 | + |
| 84 | + @property |
| 85 | + def nickname(self): |
| 86 | + return self.text.replace(".", "") |
| 87 | + |
| 88 | + @property |
| 89 | + def gitname(self): |
| 90 | + return "v" + self.text |
| 91 | + |
| 92 | + def next_minor_release(self): |
| 93 | + return self.__class__(f"{self.major}.{int(self.minor)+1}.0a0") |
| 94 | + |
| 95 | + def as_tuple(self): |
| 96 | + return (self.major, self.minor, self.patch, self.level, self.serial) |
| 97 | + |
| 98 | + @property |
| 99 | + def committed_at(self): |
| 100 | + # Fetch the epoch of the tagged commit for build reproducibility. |
| 101 | + proc = subprocess.run( |
| 102 | + ["git", "log", self.gitname, "-1", "--pretty=%ct"], stdout=subprocess.PIPE |
| 103 | + ) |
| 104 | + if proc.returncode != 0: |
| 105 | + error(f"Couldn't fetch the epoch of tag {self.gitname}") |
| 106 | + return datetime.datetime.fromtimestamp( |
| 107 | + int(proc.stdout.decode().strip()), tz=datetime.timezone.utc |
| 108 | + ) |
| 109 | + |
| 110 | + |
30 | 111 | def error(*msgs):
|
31 | 112 | print("**ERROR**", file=sys.stderr)
|
32 | 113 | for msg in msgs:
|
@@ -485,88 +566,6 @@ def scp(from_loc, to_loc):
|
485 | 566 | )
|
486 | 567 |
|
487 | 568 |
|
488 |
| -class Tag: |
489 |
| - |
490 |
| - def __init__(self, tag_name): |
491 |
| - # if tag is ".", use current directory name as tag |
492 |
| - # e.g. if current directory name is "3.4.6", |
493 |
| - # "release.py --bump 3.4.6" and "release.py --bump ." are the same |
494 |
| - if tag_name == ".": |
495 |
| - tag_name = os.path.basename(os.getcwd()) |
496 |
| - result = tag_cre.match(tag_name) |
497 |
| - if result is None: |
498 |
| - error(f"tag {tag_name} is not valid") |
499 |
| - data = list(result.groups()) |
500 |
| - if data[3] is None: |
501 |
| - # A final release. |
502 |
| - self.is_final = True |
503 |
| - data[3] = "f" |
504 |
| - else: |
505 |
| - self.is_final = False |
506 |
| - # For everything else, None means 0. |
507 |
| - for i, thing in enumerate(data): |
508 |
| - if thing is None: |
509 |
| - data[i] = 0 |
510 |
| - self.major = int(data[0]) |
511 |
| - self.minor = int(data[1]) |
512 |
| - self.patch = int(data[2]) |
513 |
| - self.level = data[3] |
514 |
| - self.serial = int(data[4]) |
515 |
| - # This has the effect of normalizing the version. |
516 |
| - self.text = self.normalized() |
517 |
| - if self.level != "f": |
518 |
| - self.text += self.level + str(self.serial) |
519 |
| - self.basic_version = f"{self.major}.{self.minor}" |
520 |
| - |
521 |
| - def __str__(self): |
522 |
| - return self.text |
523 |
| - |
524 |
| - def normalized(self): |
525 |
| - return f"{self.major}.{self.minor}.{self.patch}" |
526 |
| - |
527 |
| - @property |
528 |
| - def branch(self): |
529 |
| - return "main" if self.is_alpha_release else f"{self.major}.{self.minor}" |
530 |
| - |
531 |
| - @property |
532 |
| - def is_alpha_release(self): |
533 |
| - return self.level == "a" |
534 |
| - |
535 |
| - @property |
536 |
| - def is_release_candidate(self): |
537 |
| - return self.level == "rc" |
538 |
| - |
539 |
| - @property |
540 |
| - def is_feature_freeze_release(self): |
541 |
| - return self.level == "b" and self.serial == 1 |
542 |
| - |
543 |
| - @property |
544 |
| - def nickname(self): |
545 |
| - return self.text.replace(".", "") |
546 |
| - |
547 |
| - @property |
548 |
| - def gitname(self): |
549 |
| - return "v" + self.text |
550 |
| - |
551 |
| - def next_minor_release(self): |
552 |
| - return self.__class__(f"{self.major}.{int(self.minor)+1}.0a0") |
553 |
| - |
554 |
| - def as_tuple(self): |
555 |
| - return (self.major, self.minor, self.patch, self.level, self.serial) |
556 |
| - |
557 |
| - @property |
558 |
| - def committed_at(self): |
559 |
| - # Fetch the epoch of the tagged commit for build reproducibility. |
560 |
| - proc = subprocess.run( |
561 |
| - ["git", "log", self.gitname, "-1", "--pretty=%ct"], stdout=subprocess.PIPE |
562 |
| - ) |
563 |
| - if proc.returncode != 0: |
564 |
| - error(f"Couldn't fetch the epoch of tag {self.gitname}") |
565 |
| - return datetime.datetime.fromtimestamp( |
566 |
| - int(proc.stdout.decode().strip()), tz=datetime.timezone.utc |
567 |
| - ) |
568 |
| - |
569 |
| - |
570 | 569 | def make_tag(tag):
|
571 | 570 | # make sure we've run blurb export
|
572 | 571 | good_files = glob.glob("Misc/NEWS.d/" + str(tag) + ".rst")
|
|
0 commit comments