From e664c485e5798eb524e5199c6f1dad35ade014c3 Mon Sep 17 00:00:00 2001 From: yma Date: Fri, 1 Mar 2024 15:12:40 +0800 Subject: [PATCH] FIX multiple type of npm bin fieldd deserialization issue --- .../content/PackageMetadataGeneratorTest.java | 43 +++++++++++++++++- .../resources/metadata/version-bin-1.json | 30 ++++++++++++ .../resources/metadata/version-bin-2.json | 28 ++++++++++++ .../test/resources/tarball/version-bin-1.tgz | Bin 0 -> 1613 bytes .../test/resources/tarball/version-bin-2.tgz | Bin 0 -> 1608 bytes .../indy/pkg/npm/model/VersionMetadata.java | 16 +++++++ .../model/converter/ObjectToBinConverter.java | 42 +++++++++++++++++ 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 addons/pkg-npm/common/src/test/resources/metadata/version-bin-1.json create mode 100644 addons/pkg-npm/common/src/test/resources/metadata/version-bin-2.json create mode 100644 addons/pkg-npm/common/src/test/resources/tarball/version-bin-1.tgz create mode 100644 addons/pkg-npm/common/src/test/resources/tarball/version-bin-2.tgz create mode 100644 addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/converter/ObjectToBinConverter.java diff --git a/addons/pkg-npm/common/src/test/java/org/commonjava/indy/pkg/npm/content/PackageMetadataGeneratorTest.java b/addons/pkg-npm/common/src/test/java/org/commonjava/indy/pkg/npm/content/PackageMetadataGeneratorTest.java index 2aaeb0fa30..8caffa06aa 100644 --- a/addons/pkg-npm/common/src/test/java/org/commonjava/indy/pkg/npm/content/PackageMetadataGeneratorTest.java +++ b/addons/pkg-npm/common/src/test/java/org/commonjava/indy/pkg/npm/content/PackageMetadataGeneratorTest.java @@ -147,6 +147,47 @@ public void generateMetadataWhenMissing() throws Exception assertNotNull(after); } + @Test + public void testSingleBinFieldWhenGenerateFromTarball() throws Exception + { + ChangeSummary summary = new ChangeSummary( "test","Init NPM hosted repo." ); + final HostedRepository hostedRepository = new HostedRepository( NPM_PKG_KEY, "npm-builds" ); + initStore(hostedRepository, summary); + + final KeyedLocation location = LocationUtils.toLocation( hostedRepository ); + + storeFile( location, "jquery/-/jquery-9.0.5.tgz", "tarball/version-bin-1.tgz"); + storeFile( location, "jquery/-/jquery-9.0.6.tgz", "tarball/version-bin-2.tgz"); + storeFile( location, "jquery/9.0.5", "metadata/version-bin-1.json" ); + storeFile( location, "jquery/9.0.6", "metadata/version-bin-2.json" ); + + final String jqueryMetadataPath = "jquery/package.json"; + + // Check the package metadata before generation. + Transfer before = fileManager.retrieve( hostedRepository, jqueryMetadataPath ); + assertNull(before); + + Transfer metadataFile = generator.generateFileContent( hostedRepository, jqueryMetadataPath, new EventMetadata( ) ); + assertNotNull(metadataFile); + + final IndyObjectMapper mapper = new IndyObjectMapper( true ); + try ( InputStream input = metadataFile.openInputStream() ) + { + PackageMetadata packageMetadata = mapper.readValue( input, PackageMetadata.class ); + + assertNotNull( packageMetadata ); + assertEquals( 2, packageMetadata.getVersions().size()); + assertEquals(1, packageMetadata.getVersions().get("9.0.5").getBin().size()); + assertEquals( 1, packageMetadata.getVersions().get("9.0.6").getBin().size() ); + assertEquals("./lib/json.js", packageMetadata.getVersions().get("9.0.5").getBin().get( "json" )); + assertEquals("./lib/json.js", packageMetadata.getVersions().get("9.0.6").getBin().get( "json" )); + } + + // Check the package metadata after generation. + Transfer after = fileManager.retrieve( hostedRepository, jqueryMetadataPath ); + assertNotNull(after); + } + @Test public void generateMetadataWhenMissingForScoped() throws Exception { @@ -222,7 +263,7 @@ private void verifyMetadata( Transfer metadataFile ) throws Exception PackageMetadata packageMetadata = mapper.readValue( input, PackageMetadata.class ); assertNotNull( packageMetadata ); - assertEquals( 2, packageMetadata.getVersions().size()); + assertEquals( 1, packageMetadata.getVersions().size()); assertEquals("Unexpected package name.", "json", packageMetadata.getName()); assertEquals( "Unexpected latest version.","9.0.6", packageMetadata.getDistTags().getLatest() ); } diff --git a/addons/pkg-npm/common/src/test/resources/metadata/version-bin-1.json b/addons/pkg-npm/common/src/test/resources/metadata/version-bin-1.json new file mode 100644 index 0000000000..9a8903b4e2 --- /dev/null +++ b/addons/pkg-npm/common/src/test/resources/metadata/version-bin-1.json @@ -0,0 +1,30 @@ +{ + "name": "json", + "description": "a 'json' command for massaging and processing JSON on the command line", + "version": "9.0.5", + "repository": { + "type": "git", + "url": "git://github.com/trentm/json.git" + }, + "author": "Trent Mick (http://trentm.com)", + "main": "./lib/json.js", + "directories": { + "man": "./man/man1" + }, + "bin": "./lib/json.js", + "scripts": { + "test": "make test" + }, + "engines": { + "node": ">=0.10.0" + }, + "keywords": ["json", "jsontool", "filter", "command", "shell"], + "devDependencies": { + "uglify-js": "1.1.x", + "nodeunit": "0.8.x", + "ansidiff": "1.0", + "ben": "0.0.x", + "async": "0.1.22", + "semver": "1.1.0" + } +} \ No newline at end of file diff --git a/addons/pkg-npm/common/src/test/resources/metadata/version-bin-2.json b/addons/pkg-npm/common/src/test/resources/metadata/version-bin-2.json new file mode 100644 index 0000000000..9f7785c42c --- /dev/null +++ b/addons/pkg-npm/common/src/test/resources/metadata/version-bin-2.json @@ -0,0 +1,28 @@ +{ + "name": "json", + "description": "a 'json' command for massaging and processing JSON on the command line", + "version": "9.0.6", + "repository": { + "type": "git", + "url": "git://github.com/trentm/json.git" + }, + "author": "Trent Mick (http://trentm.com)", + "main": "./lib/json.js", + "man": ["./man/man1/json.1"], + "bin": "./lib/json.js", + "scripts": { + "test": "make test" + }, + "engines": { + "node": ">=0.10.0" + }, + "keywords": ["json", "jsontool", "filter", "command", "shell"], + "devDependencies": { + "uglify-js": "1.1.x", + "nodeunit": "0.8.x", + "ansidiff": "1.0", + "ben": "0.0.x", + "async": "0.1.22", + "semver": "1.1.0" + } +} diff --git a/addons/pkg-npm/common/src/test/resources/tarball/version-bin-1.tgz b/addons/pkg-npm/common/src/test/resources/tarball/version-bin-1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..557b897a61136df9552ad61a0646cf72dde7a2dd GIT binary patch literal 1613 zcmWIWW@Zs#00EEm#0W40N^meJFcc&vXD6no>W7B#GO%YPJWS05Vh~+g!Og(P@|BT+ z0jxU!YzhYh2Z||ofF=n6O^J{9b#(R*j?mYOhZ=}tUOT3F$qAy#=?O^*AAEhnKJbTi z1T-*BkYH99kY@a-rNH*_y@3F$jI&eI0-p(enhtLom$e8go|`{s{_5!w0TU*#nm&8R z9Og;6B1Rh{vo>E;-MMt}({FN**B*)NW@HHPX6Ja6#K0E?bQ{Qh*j;{@iGe``$^TGi z>tz+^=fT|$3Wst`x0eQO^gC=IaQC-p*t8}VzaUOdtrZe8CNwab9eJQK{m9y6_ie!) ztNvM+7hamusCe<`-QDHq%k6X|y0>H~L~YJ^-P5;@L-WAXux)Wl4V(w3O^M!g$E5cH zt9EZ{Z-HM(P&;Ho3i&Y=YGx=t=BAG_P#YN zbYL;OzrA^_*RRHwfb^>!YaUDdFP&bPBUsIS%iM706BqYyg%?EUuJ2tsi+|Au@tN;$ z)Gn|O>z&Z`%KXiuZ~I)&PEdSfB;kDO!PMhkX$uct>vf(aR9=L*1mkB z`a4{c=eN(%=FdlRkMP|nuvpn}Z07v(E6XH~ZK?FAnDrrL*}Db*&9*7Ld%ok&hLrrC zMLVXPYF?UgN4Rwz+tNkrKgzzDzkoHi;oSe2&8w&A{C=(L7=2@SvW;My0{HR*i_i$17V|`GB-Z^W{n-5HjplHJ$ zp)5cddE}%BOWE)wi5a(~q)S5sgE*#34tB!a%z+0CRa7_*F}+L(VKkCkpxM~@+1Q{% z{rU4(s$wEfmb_|R5;kSWGu7wIQ=Tnto@yw?%*n{crr9!U&XGrxE^x2W;s^Lsay}VCP z^7cNXt!;d!*hlLu*X7eaMvb$)y)TvMuHo(V?cq7AtLt-0SZ-MpPu%aftBpF+k_}$X z+ms&MX8c}h?pgkGSN*CFU)WK4Y|Y&CNwrg}LuK~OF!x?AESxj{(zUFp`4O9o*5+Mi zUAuFc@Rj_vS596O*VCDCNKv$`aM8cj2d3FM-rsXe+`ax(>U0 z*1c8t{?R3C_x^EDXf1!(SMKS~EIrTvOij2-)sc+Wcg*Ka7oFVBGTUmI&;NZ2?>jtG z-R~ZM?>770uIxEA3)G}Hy^;gxSlvLA&Jth*gQ79On~_O`8F!flExs7uI)YfRc!uX% zoFy2>y`z)*zy0A>|w86m)%l?`Md3lO#f9lVJJ!~+0(iaz83 literal 0 HcmV?d00001 diff --git a/addons/pkg-npm/common/src/test/resources/tarball/version-bin-2.tgz b/addons/pkg-npm/common/src/test/resources/tarball/version-bin-2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..f6d43d6f0f3ad1ce586e31dd296be29ff054df18 GIT binary patch literal 1608 zcmWIWW@Zs#0D;Q%#0W40N^meJFcc&vXD6no>W7B#GO!;{c$j(uh(UB|1vdjD%U4DQ z2C(h`uqhl294MyT0h%NPG$lUX*U{NOI6_}99%>+pc~3CSOHL3?PESZm_~7dk_JKdF zBcOq4f&{a=fHdPrEd{oZ?+pZ4Wt^Rw7Who)({y;#xU5A`@!b45^H)!g2$(Q=)%4jj z<}gpn6*1ZvnYH<%>dvK$pMH~jy!J?BHzPxUH#^6pBnG}HpxZ$1!|w7eObiSnNdAX9 zTQ93PKM(G9P&k~&bbD#gM!&-b0(XClhD~c?@w>$6$STS#EM#z?O=8ZINjpm4oOmv> zsH^^Xx_PcxTg3D4_wMff{B%Qt&c#K|DQ73?O3jTC3}T!X_RX*AfN+y;XY{5^C37!` zuI^2p>mbs5g;#mW_GK(CyX^Mw-)ppZX7MJ< zavx_%|4vvvQLn?sB%;*iTIQ?sWg0v3Ct7jeD%G6%MCJRd`vKuR>rAH=*?Am_OWB$H zJ@DU+5+|)w_cwH3+j;ML4^QIsi!-LPthWi>)WN&WBJfB})hYKcPbZ$Ay#9dr|FmPr zkKSC-(6?po4My(imsuA4l|JmV+E;X5>gNd`Z64o@+|~T?_6@G))jQ7Y2ubf*v}4+- z#-%TIh;waZUD`KI`-Z(E|1PH3Q!dwGj0|QdpIkakh3Tt$RO;_tKUCC~K0ESUHJoXwm-p#O-ri@l zwT;gd`)Hlzx_r9FsBxCJ_oWiuHN3sPJv?W1b$!mM+xW0b>d0MHJG?$w%5=Q` zN45CgfbCJTHh=$R@-Cd)r>cF=!fr}ve}P4M{ok8+RrTe#a(>oqT3MTT)YtQ-WpMwL ze>Pu?yn_wzJURNX2%K3L&v!E`0Y)$=8Uwr;nM9az7gx}di{Y&!hy{yhc!tGUctK2s z6<^531E~0dfwzrrKql#h8O+r%^O2J*sE~nyC5;R~f5Kc%N|A$Z19F&wl0FP9X*>fA cMYs=OR*{ww0=!w-KnAh^VJpzVYgs@%0I@DX)c^nh literal 0 HcmV?d00001 diff --git a/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/VersionMetadata.java b/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/VersionMetadata.java index 3684e506ff..d56b7130c0 100644 --- a/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/VersionMetadata.java +++ b/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/VersionMetadata.java @@ -20,12 +20,15 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import org.commonjava.indy.pkg.npm.model.converter.ObjectToBinConverter; import org.commonjava.indy.pkg.npm.model.converter.ObjectToLicenseConverter; import java.io.Serializable; import java.util.List; import java.util.Map; +import static org.commonjava.indy.pkg.npm.model.converter.ObjectToBinConverter.SINGLE_BIN; + @ApiModel( description = "Specify all the corresponding versions metadata for the package." ) public class VersionMetadata implements Serializable, Comparable @@ -73,6 +76,8 @@ public class VersionMetadata private Map devDependencies; + @ApiModelProperty( required = false ) + @JsonDeserialize(converter = ObjectToBinConverter.class) private Map bin; private Map jsdomVersions; @@ -310,6 +315,17 @@ public Map getDevDependencies() public Map getBin() { + if ( null == bin ) + { + return null; + } + String value = bin.get( SINGLE_BIN ); + if ( null != value ) + { + bin.remove( SINGLE_BIN ); + // ref https://docs.npmjs.com/cli/v7/configuring-npm/package-json#bin + bin.put( name, value ); + } return bin; } diff --git a/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/converter/ObjectToBinConverter.java b/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/converter/ObjectToBinConverter.java new file mode 100644 index 0000000000..19274bdc9a --- /dev/null +++ b/addons/pkg-npm/model-java/src/main/java/org/commonjava/indy/pkg/npm/model/converter/ObjectToBinConverter.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2011-2023 Red Hat, Inc. (https://github.com/Commonjava/indy) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.commonjava.indy.pkg.npm.model.converter; + +import com.fasterxml.jackson.databind.util.StdConverter; + +import java.util.HashMap; +import java.util.Map; + +public class ObjectToBinConverter + extends StdConverter> +{ + + public static final String SINGLE_BIN = "SINGLE_BIN"; + + @Override + public Map convert( Object o ) + { + if ( o instanceof Map ) + { + return (Map) o; + } + // Use SPDX expressions, ref https://docs.npmjs.com/cli/v7/configuring-npm/package-json + // parse String value to Map value + Map result = new HashMap<>(); + result.put( SINGLE_BIN, o.toString() ); + return result; + } +}