11
11
import io .apicurio .registry .model .GA ;
12
12
import io .apicurio .registry .model .GAV ;
13
13
import io .apicurio .registry .model .VersionId ;
14
+ import io .apicurio .registry .semver .SemVerConfigProperties ;
14
15
import io .apicurio .registry .storage .RegistryStorage ;
15
16
import io .apicurio .registry .storage .StorageBehaviorProperties ;
16
17
import io .apicurio .registry .storage .StorageEvent ;
113
114
import io .quarkus .security .identity .SecurityIdentity ;
114
115
import jakarta .enterprise .event .Event ;
115
116
import jakarta .inject .Inject ;
117
+ import jakarta .validation .ValidationException ;
116
118
import org .apache .commons .lang3 .tuple .ImmutablePair ;
117
119
import org .apache .commons .lang3 .tuple .Pair ;
118
120
import org .eclipse .microprofile .config .inject .ConfigProperty ;
121
+ import org .semver4j .Semver ;
119
122
import org .slf4j .Logger ;
120
123
121
124
import java .sql .ResultSet ;
@@ -187,6 +190,9 @@ public abstract class AbstractSqlRegistryStorage implements RegistryStorage {
187
190
@ Inject
188
191
RegistryStorageContentUtils utils ;
189
192
193
+ @ Inject
194
+ SemVerConfigProperties semVerConfigProps ;
195
+
190
196
protected SqlStatements sqlStatements () {
191
197
return sqlStatements ;
192
198
}
@@ -554,7 +560,6 @@ private ArtifactVersionMetaDataDto createArtifactVersionRaw(Handle handle, boole
554
560
.bind (12 , contentId ).execute ();
555
561
556
562
gav = new GAV (groupId , artifactId , finalVersion1 );
557
- createOrUpdateBranchRaw (handle , gav , BranchId .LATEST , true );
558
563
} else {
559
564
handle .createUpdate (sqlStatements .insertVersion (false )).bind (0 , globalId )
560
565
.bind (1 , normalizeGroupId (groupId )).bind (2 , artifactId ).bind (3 , version )
@@ -571,7 +576,6 @@ private ArtifactVersionMetaDataDto createArtifactVersionRaw(Handle handle, boole
571
576
}
572
577
573
578
gav = getGAVByGlobalId (handle , globalId );
574
- createOrUpdateBranchRaw (handle , gav , BranchId .LATEST , true );
575
579
}
576
580
577
581
// Insert labels into the "version_labels" table
@@ -583,6 +587,10 @@ private ArtifactVersionMetaDataDto createArtifactVersionRaw(Handle handle, boole
583
587
});
584
588
}
585
589
590
+ // Update system generated branches
591
+ createOrUpdateBranchRaw (handle , gav , BranchId .LATEST , true );
592
+ createOrUpdateSemverBranches (handle , gav );
593
+
586
594
// Create any user defined branches
587
595
if (branches != null && !branches .isEmpty ()) {
588
596
branches .forEach (branch -> {
@@ -595,6 +603,54 @@ private ArtifactVersionMetaDataDto createArtifactVersionRaw(Handle handle, boole
595
603
.map (ArtifactVersionMetaDataDtoMapper .instance ).one ();
596
604
}
597
605
606
+ /**
607
+ * If SemVer support is enabled, create (or update) the automatic system generated semantic versioning
608
+ * branches.
609
+ *
610
+ * @param handle
611
+ * @param gav
612
+ */
613
+ private void createOrUpdateSemverBranches (Handle handle , GAV gav ) {
614
+ boolean validationEnabled = semVerConfigProps .validationEnabled .get ();
615
+ boolean branchingEnabled = semVerConfigProps .branchingEnabled .get ();
616
+ boolean coerceInvalidVersions = semVerConfigProps .coerceInvalidVersions .get ();
617
+
618
+ // Validate the version if validation is enabled.
619
+ if (validationEnabled ) {
620
+ Semver semver = Semver .parse (gav .getRawVersionId ());
621
+ if (semver == null ) {
622
+ throw new ValidationException ("Version '" + gav .getRawVersionId ()
623
+ + "' does not conform to Semantic Versioning 2 format." );
624
+ }
625
+ }
626
+
627
+ // Create branches if branching is enabled
628
+ if (!branchingEnabled ) {
629
+ return ;
630
+ }
631
+
632
+ Semver semver = null ;
633
+ if (coerceInvalidVersions ) {
634
+ semver = Semver .coerce (gav .getRawVersionId ());
635
+ if (semver == null ) {
636
+ throw new ValidationException ("Version '" + gav .getRawVersionId ()
637
+ + "' cannot be coerced to Semantic Versioning 2 format." );
638
+ }
639
+ } else {
640
+ semver = Semver .parse (gav .getRawVersionId ());
641
+ if (semver == null ) {
642
+ throw new ValidationException ("Version '" + gav .getRawVersionId ()
643
+ + "' does not conform to Semantic Versioning 2 format." );
644
+ }
645
+ }
646
+ if (semver == null ) {
647
+ throw new UnreachableCodeException ("Unexpectedly reached unreachable code!" );
648
+ }
649
+ createOrUpdateBranchRaw (handle , gav , new BranchId (semver .getMajor () + ".x" ), true );
650
+ createOrUpdateBranchRaw (handle , gav , new BranchId (semver .getMajor () + "." + semver .getMinor () + ".x" ),
651
+ true );
652
+ }
653
+
598
654
/**
599
655
* Store the content in the database and return the content ID of the new row. If the content already
600
656
* exists, just return the content ID of the existing row.
@@ -3031,6 +3087,11 @@ public BranchMetaDataDto createBranch(GA ga, BranchId branchId, String descripti
3031
3087
3032
3088
@ Override
3033
3089
public void updateBranchMetaData (GA ga , BranchId branchId , EditableBranchMetaDataDto dto ) {
3090
+ BranchMetaDataDto bmd = getBranchMetaData (ga , branchId );
3091
+ if (bmd .isSystemDefined ()) {
3092
+ throw new NotAllowedException ("System generated branches cannot be modified." );
3093
+ }
3094
+
3034
3095
String modifiedBy = securityIdentity .getPrincipal ().getName ();
3035
3096
Date modifiedOn = new Date ();
3036
3097
log .debug ("Updating metadata for branch {} of {}/{}." , branchId , ga .getRawGroupIdWithNull (),
@@ -3220,6 +3281,11 @@ public VersionSearchResultsDto getBranchVersions(GA ga, BranchId branchId, int o
3220
3281
3221
3282
@ Override
3222
3283
public void appendVersionToBranch (GA ga , BranchId branchId , VersionId version ) {
3284
+ BranchMetaDataDto bmd = getBranchMetaData (ga , branchId );
3285
+ if (bmd .isSystemDefined ()) {
3286
+ throw new NotAllowedException ("System generated branches cannot be modified." );
3287
+ }
3288
+
3223
3289
try {
3224
3290
handles .withHandle (handle -> {
3225
3291
appendVersionToBranchRaw (handle , ga , branchId , version );
@@ -3257,6 +3323,11 @@ private void appendVersionToBranchRaw(Handle handle, GA ga, BranchId branchId, V
3257
3323
3258
3324
@ Override
3259
3325
public void replaceBranchVersions (GA ga , BranchId branchId , List <VersionId > versions ) {
3326
+ BranchMetaDataDto bmd = getBranchMetaData (ga , branchId );
3327
+ if (bmd .isSystemDefined ()) {
3328
+ throw new NotAllowedException ("System generated branches cannot be modified." );
3329
+ }
3330
+
3260
3331
handles .withHandle (handle -> {
3261
3332
// Delete all previous versions.
3262
3333
handle .createUpdate (sqlStatements .deleteBranchVersions ()).bind (0 , ga .getRawGroupId ())
@@ -3341,8 +3412,9 @@ private GAV getGAVByGlobalId(Handle handle, long globalId) {
3341
3412
3342
3413
@ Override
3343
3414
public void deleteBranch (GA ga , BranchId branchId ) {
3344
- if (BranchId .LATEST .equals (branchId )) {
3345
- throw new NotAllowedException ("Artifact branch 'latest' cannot be deleted." );
3415
+ BranchMetaDataDto bmd = getBranchMetaData (ga , branchId );
3416
+ if (bmd .isSystemDefined ()) {
3417
+ throw new NotAllowedException ("System generated branches cannot be deleted." );
3346
3418
}
3347
3419
3348
3420
handles .withHandleNoException (handle -> {
0 commit comments