aboutsummaryrefslogtreecommitdiffstats
path: root/vespajlib/src/main/java/com/yahoo/vespa/VersionTagger.java
blob: 925cdffe5a5e941b8047adad0d34413149af1911 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa;

import java.nio.file.Files;
import java.nio.file.Path;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * This class generates a java class based on the vtag.map file generated by dist/getversion.pl
 */
public class VersionTagger {

    public static final String V_TAG_PKG = "V_TAG_PKG";

    VersionTagger() {}

    private static void printUsage(PrintStream out) {
        out.println("Usage: java VersionTagger vtagmap pkgname outputdir");
    }

    public static void main(String[] args) {
        if (args.length < 3) {
            printUsage(System.err);
            throw new RuntimeException("bad arguments to main(): vtag.map packageName outputDirectory [outputFormat (simple or vtag)]");
        }
        try {
            VersionTagger me = new VersionTagger();
            me.runProgram(args);
        } catch (Exception e) {
            System.err.println(e);
            printUsage(System.err);
            throw new RuntimeException(e);
        }
    }

    private Map<String, String> readVtagMap(String path) {
        Map<String, String> map = new HashMap<>();
        try {
            BufferedReader in = new BufferedReader(new FileReader(path));
            String line;
            while ((line = in.readLine()) != null) {
                if (line.isBlank()) continue;
                String[] elements = line.split("\\s+", 2);
                map.put(elements[0], elements[1]);
            }
        } catch (FileNotFoundException e) {
            // Use default values
            map.put("V_TAG", "NOTAG");
            map.put("V_TAG_DATE", "NOTAG");
            map.put("V_TAG_PKG", "8.9999.0");
            map.put("V_TAG_ARCH", "NOTAG");
            map.put("V_TAG_SYSTEM", "NOTAG");
            map.put("V_TAG_SYSTEM_REV", "NOTAG");
            map.put("V_TAG_BUILDER", "NOTAG");
            map.put("V_TAG_COMPONENT", "8.9999.0");
            map.put("V_TAG_COMMIT_SHA", "badc0ffe");
            map.put("V_TAG_COMMIT_DATE", "0");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return map;
    }
    private enum Format {
        SIMPLE,
        VTAG
    }

    void runProgram(String[] args)  throws IOException {
        String vtagmapPath = args[0];
        String packageName = args[1];
        String dirName = args[2] + "/" + packageName.replaceAll("\\.", "/");
        Format format = args.length >= 4 ? Format.valueOf(args[3].toUpperCase()) : Format.SIMPLE;
        File outDir = new File(dirName);
        if (!outDir.isDirectory() && !outDir.mkdirs()) {
            throw new IOException("could not create directory " + outDir);
        }

        String className = format == Format.SIMPLE ? "VespaVersion" : "Vtag";
        String outFile = dirName + "/" + className +".java";
        Path outPath = Path.of(outFile);
        Path tmpPath = Path.of(outFile + ".tmp");
        var out = Files.newOutputStream(tmpPath);
        OutputStreamWriter writer = new OutputStreamWriter(out);
        System.err.println("generating: " + outFile);

        Map<String, String> vtagMap = readVtagMap(vtagmapPath);
        writer.write(String.format("package %s;\n\n", packageName));

        if (format == Format.VTAG) {
            writer.write("import java.time.Instant;\n");
            writer.write("import com.yahoo.component.Version;\n");
        }

        writer.write(String.format("\npublic class %s {\n", className));
        if (!vtagMap.containsKey(V_TAG_PKG)) {
            throw new RuntimeException("V_TAG_PKG not present in map file");
        }
        switch (format) {
            case SIMPLE:
                String version = vtagMap.get(V_TAG_PKG);
                String elements[] = version.split("\\.");
                writer.write(String.format("    public static final int major = %s;\n", elements[0]));
                writer.write(String.format("    public static final int minor = %s;\n", elements[1]));
                writer.write(String.format("    public static final int micro = %s;\n", elements[2]));
                break;
            case VTAG:
                long commitDateSecs = 0;
                for (var entry : vtagMap.entrySet()) {
                    var key = entry.getKey();
                    var value = entry.getValue();
                    try {
                        writer.write(String.format("    public static final String %s = \"%s\";\n", key, value));
                        if ("V_TAG_COMMIT_DATE".equals(key)) {
                            commitDateSecs = Long.parseLong(value);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                };
                writer.write("    public static final Version currentVersion = new Version(V_TAG_COMPONENT);\n");
                writer.write("    public static final String commitSha = V_TAG_COMMIT_SHA;\n");
                writer.write("    public static final Instant commitDate = Instant.ofEpochSecond(" + commitDateSecs +");\n");
                break;
        }
        writer.write("}\n");
        writer.close();
        out.close();
        if (Files.exists(outPath)) {
            byte[] tmpBytes = Files.readAllBytes(tmpPath);
            byte[] oldBytes = Files.readAllBytes(outPath);
            if (Arrays.equals(tmpBytes, oldBytes)) {
                Files.delete(tmpPath);
                return;
            }
        }
        Files.deleteIfExists(outPath);
        Files.move(tmpPath, outPath);
    }

}