github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/scripts/versioninfo-generator/main.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "strings" 8 "time" 9 10 "github.com/ActiveState/cli/internal/assets" 11 "github.com/ActiveState/cli/internal/errs" 12 "github.com/blang/semver" 13 ) 14 15 const ( 16 versionInfoAssetsFileName = "versioninfo.json" 17 versionInfoLegalCopyright = "© ActiveState Software, Inc. %d" 18 ) 19 20 type versionInfo struct { 21 FixedFileInfo FixedFileInfo `json:"FixedFileInfo"` 22 StringFileInfo StringFileInfo `json:"StringFileInfo"` 23 24 // The remainder is data we don't care about but need 25 // to preserve in the JSON file. 26 VarFileInfo VarFileInfo `json:"VarFileInfo"` 27 IconPath string `json:"IconPath"` 28 ManifestPath string `json:"ManifestPath"` 29 } 30 31 type FixedFileInfo struct { 32 FileVersion FileVersion `json:"FileVersion"` 33 ProductVersion ProductVersion `json:"ProductVersion"` 34 35 // The remainder is data we don't care about but need 36 // to preserve in the JSON file. 37 FileFlagsMask string `json:"FileFlagsMask"` 38 FileFlags string `json:"FileFlags"` 39 FileOS string `json:"FileOS"` 40 FileType string `json:"FileType"` 41 FileSubType string `json:"FileSubType"` 42 } 43 44 type FileVersion struct { 45 Major int `json:"Major"` 46 Minor int `json:"Minor"` 47 Patch int `json:"Patch"` 48 Build int `json:"Build"` 49 } 50 51 type ProductVersion struct { 52 Major int `json:"Major"` 53 Minor int `json:"Minor"` 54 Patch int `json:"Patch"` 55 Build int `json:"Build"` 56 } 57 58 type StringFileInfo struct { 59 FileVersion string `json:"FileVersion"` 60 ProductVersion string `json:"ProductVersion"` 61 62 // The remainder is data we don't care about but need 63 // to preserve in the JSON file. 64 Comments string `json:"Comments"` 65 CompanyName string `json:"CompanyName"` 66 FileDescription string `json:"FileDescription"` 67 InternalName string `json:"InternalName"` 68 LegalCopyright string `json:"LegalCopyright"` 69 LegalTrademarks string `json:"LegalTrademarks"` 70 OriginalFilename string `json:"OriginalFilename"` 71 PrivateBuild string `json:"PrivateBuild"` 72 ProductName string `json:"ProductName"` 73 SpecialBuild string `json:"SpecialBuild"` 74 } 75 76 type VarFileInfo struct { 77 Translation Translation `json:"Translation"` 78 } 79 80 type Translation struct { 81 LangID string `json:"LangID"` 82 CharsetID string `json:"CharsetID"` 83 } 84 85 func main() { 86 if err := run(); err != nil { 87 panic(err) 88 } 89 } 90 91 func run() error { 92 if len(os.Args) != 4 { 93 return errs.New("Usage: versioninfo-generator <version.txt> <versioninfo.json>") 94 } 95 96 versionFile := os.Args[1] 97 versionInfoFilePath := os.Args[2] 98 productName := os.Args[3] 99 100 // Read version.txt 101 version, err := os.ReadFile(versionFile) 102 if err != nil { 103 return errs.Wrap(err, "failed to read version.txt") 104 } 105 106 // The goversioninfo library does not support prerelease versions 107 if strings.Contains(string(version), "-") { 108 parts := strings.SplitN(string(version), "-", 2) 109 version = []byte(parts[0]) 110 } 111 112 // Parse semver from version.txt 113 semver, err := semver.Parse(string(version)) 114 if err != nil { 115 return errs.Wrap(err, "failed to parse version.txt") 116 } 117 118 versionInfoFile, err := assets.ReadFileBytes(versionInfoAssetsFileName) 119 if err != nil { 120 return errs.Wrap(err, "failed to read versioninfo.json") 121 } 122 123 // Parse versioninfo.json to data map 124 var data map[string]interface{} 125 if err := json.Unmarshal(versionInfoFile, &data); err != nil { 126 return errs.Wrap(err, "failed to parse versioninfo.json") 127 } 128 129 // Parse versioninfo.json 130 var versionInfo versionInfo 131 if err := json.Unmarshal(versionInfoFile, &versionInfo); err != nil { 132 return errs.Wrap(err, "failed to parse versioninfo.json") 133 } 134 135 // Update versioninfo.json 136 versionInfo.FixedFileInfo.FileVersion.Major = int(semver.Major) 137 versionInfo.FixedFileInfo.FileVersion.Minor = int(semver.Minor) 138 versionInfo.FixedFileInfo.FileVersion.Patch = int(semver.Patch) 139 versionInfo.FixedFileInfo.ProductVersion.Major = int(semver.Major) 140 versionInfo.FixedFileInfo.ProductVersion.Minor = int(semver.Minor) 141 versionInfo.FixedFileInfo.ProductVersion.Patch = int(semver.Patch) 142 versionInfo.StringFileInfo.FileVersion = semver.String() 143 versionInfo.StringFileInfo.ProductVersion = semver.String() 144 versionInfo.StringFileInfo.ProductName = productName 145 versionInfo.StringFileInfo.LegalCopyright = fmt.Sprintf(versionInfoLegalCopyright, time.Now().Year()) 146 147 // Marshal the updated versioninfo.json 148 finalJSON, err := json.MarshalIndent(versionInfo, "", " ") 149 if err != nil { 150 return errs.Wrap(err, "failed to marshal versioninfo.json") 151 } 152 153 // Save the final JSON back to the file 154 err = os.WriteFile(versionInfoFilePath, finalJSON, 0644) 155 if err != nil { 156 return errs.Wrap(err, "failed to write versioninfo.json") 157 } 158 fmt.Println("Successfully generated versioninfo.json at ", versionInfoFilePath) 159 160 return nil 161 162 }