From b7e08e88b52f009cbbf3caed56cb8f507feeb3bb Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Thu, 26 Nov 2009 20:25:13 +0100
Subject: support @-style list files on the command line

Task-number: QTBUG-4099
---
 .../lupdate/testdata/good/respfile/lupdatecmd      |   2 +
 .../testdata/good/respfile/project.ts.result       |  17 +++
 .../lupdate/testdata/good/respfile/source1.cpp     |  49 ++++++++
 .../lupdate/testdata/good/respfile/source2.cpp     |  49 ++++++++
 .../lupdate/testdata/good/respfile/sources.lst     |   2 +
 .../lupdate/testdata/good/respfile/tsfiles.lst     |   1 +
 tools/linguist/lupdate/main.cpp                    | 140 ++++++++++++---------
 7 files changed, 199 insertions(+), 61 deletions(-)
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/lupdatecmd
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/project.ts.result
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/source1.cpp
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/source2.cpp
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/sources.lst
 create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/tsfiles.lst

diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/lupdatecmd b/tests/auto/linguist/lupdate/testdata/good/respfile/lupdatecmd
new file mode 100644
index 0000000..6f198ab
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/lupdatecmd
@@ -0,0 +1,2 @@
+# Add the command that lupdate should run here. If it can't find anything it will default to
+lupdate -silent @sources.lst -ts @tsfiles.lst
diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/respfile/project.ts.result
new file mode 100644
index 0000000..3a864a2
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/project.ts.result
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0">
+<context>
+    <name>Dialog2</name>
+    <message>
+        <location filename="source1.cpp" line="47"/>
+        <source>func1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="source2.cpp" line="47"/>
+        <source>func2</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+</TS>
diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/source1.cpp b/tests/auto/linguist/lupdate/testdata/good/respfile/source1.cpp
new file mode 100644
index 0000000..33642c4
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/source1.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// IMPORTANT!!!! If you want to add testdata to this file,
+// always add it to the end in order to not change the linenumbers of translations!!!
+
+void Dialog2::func3()
+{
+    tr("func1");
+}
+
diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/source2.cpp b/tests/auto/linguist/lupdate/testdata/good/respfile/source2.cpp
new file mode 100644
index 0000000..8e496a8
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/source2.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// IMPORTANT!!!! If you want to add testdata to this file,
+// always add it to the end in order to not change the linenumbers of translations!!!
+
+void Dialog2::func3()
+{
+    tr("func2");
+}
+
diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/sources.lst b/tests/auto/linguist/lupdate/testdata/good/respfile/sources.lst
new file mode 100644
index 0000000..430937e
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/sources.lst
@@ -0,0 +1,2 @@
+source1.cpp
+source2.cpp
diff --git a/tests/auto/linguist/lupdate/testdata/good/respfile/tsfiles.lst b/tests/auto/linguist/lupdate/testdata/good/respfile/tsfiles.lst
new file mode 100644
index 0000000..f3eb71f
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/respfile/tsfiles.lst
@@ -0,0 +1 @@
+project.ts
diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp
index 9a9af68..5be13e1 100644
--- a/tools/linguist/lupdate/main.cpp
+++ b/tools/linguist/lupdate/main.cpp
@@ -84,7 +84,7 @@ static void printUsage()
     printOut(QObject::tr(
         "Usage:\n"
         "    lupdate [options] [project-file]...\n"
-        "    lupdate [options] [source-file|path]... -ts ts-files\n\n"
+        "    lupdate [options] [source-file|path|@lst-file]... -ts ts-files|@lst-file\n\n"
         "lupdate is part of Qt's Linguist tool chain. It extracts translatable\n"
         "messages from Qt UI files, C++, Java and JavaScript/QtScript source code.\n"
         "Extracted messages are stored in textual translation source files (typically\n"
@@ -128,6 +128,8 @@ static void printUsage()
         "           Guessed from the file name if not specified.\n"
         "    -version\n"
         "           Display the version of lupdate and exit.\n"
+        "    @lst-file\n"
+        "           Read additional file names (one per line) from lst-file.\n"
     ).arg(m_defaultExtensions));
 }
 
@@ -374,78 +376,94 @@ int main(int argc, char **argv)
         }
 
         numFiles++;
-
-        QString fullText;
+        QStringList files;
+        if (arg.startsWith(QLatin1String("@"))) {
+            QFile lstFile(arg.mid(1));
+            if (!lstFile.open(QIODevice::ReadOnly)) {
+                qWarning("lupdate error: List file '%s' is not readable",
+                         qPrintable(lstFile.fileName()));
+                return 1;
+            }
+            while (!lstFile.atEnd())
+                files << QString::fromLocal8Bit(lstFile.readLine().trimmed());
+        } else {
+            files << arg;
+        }
 
         codecForTr.clear();
         codecForSource.clear();
 
         if (metTsFlag) {
-            bool found = false;
-            foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
-                if (arg.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
-                    QFileInfo fi(arg);
-                    if (!fi.exists() || fi.isWritable()) {
-                        tsFileNames.append(QFileInfo(arg).absoluteFilePath());
-                    } else {
-                        qWarning("lupdate warning: For some reason, '%s' is not writable.\n",
-                                qPrintable(arg));
+            foreach (const QString &file, files) {
+                bool found = false;
+                foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
+                    if (file.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
+                        QFileInfo fi(file);
+                        if (!fi.exists() || fi.isWritable()) {
+                            tsFileNames.append(QFileInfo(file).absoluteFilePath());
+                        } else {
+                            qWarning("lupdate warning: For some reason, '%s' is not writable.\n",
+                                    qPrintable(file));
+                        }
+                        found = true;
+                        break;
                     }
-                    found = true;
-                    break;
+                }
+                if (!found) {
+                    qWarning("lupdate error: File '%s' has no recognized extension\n",
+                             qPrintable(file));
+                    return 1;
                 }
             }
-            if (!found) {
-                qWarning("lupdate error: File '%s' has no recognized extension\n",
-                         qPrintable(arg));
-                return 1;
-            }
-        } else if (arg.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
-                || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
-            proFiles << arg;
         } else {
-            QFileInfo fi(arg);
-            if (!fi.exists()) {
-                qWarning("lupdate error: File '%s' does not exists\n", qPrintable(arg));
-                return 1;
-            } else if (fi.isDir()) {
-                if (options & Verbose)
-                    printOut(QObject::tr("Scanning directory '%1'...").arg(arg));
-                QDir dir = QDir(fi.filePath());
-                projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
-                if (extensionsNameFilters.isEmpty()) {
-                    foreach (QString ext, extensions.split(QLatin1Char(','))) {
-                        ext = ext.trimmed();
-                        if (ext.startsWith(QLatin1Char('.')))
-                            ext.remove(0, 1);
-                        extensionsNameFilters.insert(ext);
-                    }
+            foreach (const QString &file, files) {
+                QFileInfo fi(file);
+                if (!fi.exists()) {
+                    qWarning("lupdate error: File '%s' does not exists\n", qPrintable(file));
+                    return 1;
                 }
-                QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
-                if (recursiveScan)
-                    filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
-                QFileInfoList fileinfolist;
-                recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
-                int scanRootLen = dir.absolutePath().length();
-                foreach (const QFileInfo &fi, fileinfolist) {
-                    QString fn = QDir::cleanPath(fi.absoluteFilePath());
-                    sourceFiles << fn;
-
-                    if (!fn.endsWith(QLatin1String(".java"))
-                        && !fn.endsWith(QLatin1String(".ui"))
-                        && !fn.endsWith(QLatin1String(".js"))
-                        && !fn.endsWith(QLatin1String(".qs"))) {
-                        int offset = 0;
-                        int depth = 0;
-                        do {
-                            offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
-                            QString ffn = fn.mid(offset + 1);
-                            allCSources.insert(ffn, fn);
-                        } while (++depth < 3 && offset > scanRootLen);
+                if (file.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
+                    || file.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
+                    proFiles << file;
+                } else if (fi.isDir()) {
+                    if (options & Verbose)
+                        printOut(QObject::tr("Scanning directory '%1'...").arg(file));
+                    QDir dir = QDir(fi.filePath());
+                    projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
+                    if (extensionsNameFilters.isEmpty()) {
+                        foreach (QString ext, extensions.split(QLatin1Char(','))) {
+                            ext = ext.trimmed();
+                            if (ext.startsWith(QLatin1Char('.')))
+                                ext.remove(0, 1);
+                            extensionsNameFilters.insert(ext);
+                        }
+                    }
+                    QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
+                    if (recursiveScan)
+                        filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
+                    QFileInfoList fileinfolist;
+                    recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
+                    int scanRootLen = dir.absolutePath().length();
+                    foreach (const QFileInfo &fi, fileinfolist) {
+                        QString fn = QDir::cleanPath(fi.absoluteFilePath());
+                        sourceFiles << fn;
+
+                        if (!fn.endsWith(QLatin1String(".java"))
+                            && !fn.endsWith(QLatin1String(".ui"))
+                            && !fn.endsWith(QLatin1String(".js"))
+                            && !fn.endsWith(QLatin1String(".qs"))) {
+                            int offset = 0;
+                            int depth = 0;
+                            do {
+                                offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
+                                QString ffn = fn.mid(offset + 1);
+                                allCSources.insert(ffn, fn);
+                            } while (++depth < 3 && offset > scanRootLen);
+                        }
                     }
+                } else {
+                    sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
                 }
-            } else {
-                sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
             }
         }
     } // for args
-- 
cgit v0.12