superfluous_includes--
[quassel.git] / src / common / genversion.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2013 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 /** This is called at compile time and generates a suitable version.gen.
22  *  usage: genversion git_root target_file
23  */
24
25 #include <QDebug>
26 #include <QProcess>
27 #include <QString>
28 #include <QStringList>
29 #include <QRegExp>
30 #include <QFile>
31 #include <QCoreApplication>
32
33 int main(int argc, char **argv)
34 {
35     if (argc < 3) {
36         qFatal("Usage: ./genversion <git_root> <target_file>");
37         return 255;
38     }
39
40     QCoreApplication app(argc, argv);
41
42     QString gitroot = app.arguments()[1];
43     QString target = app.arguments()[2];
44     QString basever, protover, clientneeds, coreneeds, descrver, dirty;
45     QString committish, commitdate;
46
47     // check Git for information if present
48     if (QFile::exists(gitroot + "/.git")) {
49         // try to execute git-describe to get a version string
50         QProcess git;
51         git.setWorkingDirectory(gitroot);
52     #ifdef Q_OS_WIN
53         git.start("cmd.exe", QStringList() << "/C" << "git" << "describe" << "--long");
54     #else
55         git.start("git", QStringList() << "describe" << "--long");
56     #endif
57         if (git.waitForFinished(10000)) {
58             QString descr = git.readAllStandardOutput().trimmed();
59             if (!descr.isEmpty() && !descr.contains("fatal")) {
60                 // seems we have a valid git describe string
61                 descrver = descr;
62                 // check if the workdir is dirty
63         #ifdef Q_OS_WIN
64                 git.start("cmd.exe", QStringList() << "/C" << "git" << "diff-index" << "--name-only" << "HEAD");
65         #else
66                 git.start("git", QStringList() << "diff-index" << "--name-only" << "HEAD");
67         #endif
68                 if (git.waitForFinished(10000)) {
69                     if (!git.readAllStandardOutput().isEmpty()) dirty = "*";
70                 }
71                 // get a full committish
72         #ifdef Q_OS_WIN
73                 git.start("cmd.exe", QStringList() << "/C" << "git" << "rev-parse" << "HEAD");
74         #else
75                 git.start("git", QStringList() << "rev-parse" << "HEAD");
76         #endif
77                 if (git.waitForFinished(10000)) {
78                     committish = git.readAllStandardOutput().trimmed();
79                 }
80                 // Now we do some replacement magic...
81                 //QRegExp rxCheckTag("(.*)-0-g[0-9a-f]+\n$");
82                 //QRegExp rxGittify("(.*)-(\\d+)-g([0-9a-f]+)\n$");
83                 //gitversion.replace(rxCheckTag, QString("\\1%1").arg(dirty));
84                 //gitversion.replace(rxGittify, QString("\\1:git-\\3+\\2%1").arg(dirty));
85             }
86         }
87     }
88
89     // parse version.inc
90     QFile verfile(gitroot + "/version.inc");
91     if (verfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
92         QString ver = verfile.readAll();
93
94         QRegExp rxBasever("baseVersion\\s*=\\s*\"(.*)\";");
95         if (rxBasever.indexIn(ver) >= 0)
96             basever = rxBasever.cap(1);
97
98         QRegExp rxProtover("protocolVersion\\s*=\\s*(\\d+)");
99         if (rxProtover.indexIn(ver) >= 0)
100             protover = rxProtover.cap(1);
101
102         QRegExp rxClientneeds("clientNeedsProtocol\\s*=\\s*(\\d+)");
103         if (rxClientneeds.indexIn(ver) >= 0)
104             clientneeds = rxClientneeds.cap(1);
105
106         QRegExp rxCoreneeds("coreNeedsProtocol\\s*=\\s*(\\d+)");
107         if (rxCoreneeds.indexIn(ver) >= 0)
108             coreneeds = rxCoreneeds.cap(1);
109
110         if (committish.isEmpty()) {
111             QRegExp rxCommit("distCommittish\\s*=\\s*([0-9a-f]+)");
112             if (rxCommit.indexIn(ver) >= 0) committish = rxCommit.cap(1);
113         }
114
115         QRegExp rxTimestamp("distCommitDate\\s*=\\s*([0-9]+)");
116         if (rxTimestamp.indexIn(ver) >= 0) commitdate = rxTimestamp.cap(1);
117         verfile.close();
118     }
119
120     // generate the contents for version.gen
121     QByteArray contents = QString("QString buildinfo = \"%1,%2,%3,%4,%5,%6,%7,%8\";\n")
122                           .arg(basever, descrver, dirty, committish, commitdate, protover, clientneeds, coreneeds)
123                           .toAscii();
124
125     QFile gen(target);
126     if (!gen.open(QIODevice::ReadWrite | QIODevice::Text)) {
127         qFatal("%s", qPrintable(QString("Could not write %1!").arg(target)));
128         return EXIT_FAILURE;
129     }
130     QByteArray oldContents = gen.readAll();
131     if (oldContents != contents) { // only touch the file if something changed
132         gen.seek(0);
133         gen.resize(0);
134         gen.write(contents);
135         gen.waitForBytesWritten(10000);
136     }
137     gen.close();
138
139     return EXIT_SUCCESS;
140 }