Coverage Report

Created: 2025-06-13 06:29

/src/gdal/apps/gdalalg_main.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
*
3
* Project:  GDAL
4
* Purpose:  gdal "main" command
5
* Author:   Even Rouault <even dot rouault at spatialys.com>
6
*
7
******************************************************************************
8
* Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9
*
10
* SPDX-License-Identifier: MIT
11
****************************************************************************/
12
13
#include "gdalalg_main.h"
14
15
#include "gdal_priv.h"
16
17
//! @cond Doxygen_Suppress
18
19
#ifndef _
20
0
#define _(x) (x)
21
#endif
22
23
/************************************************************************/
24
/*                  GDALMainAlgorithm::GDALMainAlgorithm()              */
25
/************************************************************************/
26
27
GDALMainAlgorithm::GDALMainAlgorithm()
28
0
    : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
29
0
{
30
0
    for (const std::string &subAlgName :
31
0
         GDALGlobalAlgorithmRegistry::GetSingleton().GetNames())
32
0
    {
33
0
        const auto pInfo =
34
0
            GDALGlobalAlgorithmRegistry::GetSingleton().GetInfo(subAlgName);
35
0
        if (pInfo)
36
0
            RegisterSubAlgorithm(*pInfo);
37
0
    }
38
39
0
    SetCallPath({NAME});
40
41
0
    AddArg("version", 0, _("Display GDAL version and exit"), &m_version)
42
0
        .SetOnlyForCLI();
43
0
    AddArg("drivers", 0, _("Display driver list as JSON document"), &m_drivers);
44
45
0
    AddOutputStringArg(&m_output);
46
47
0
    m_longDescription = "'gdal <FILENAME>' can also be used as a shortcut for "
48
0
                        "'gdal info <FILENAME>'.\n"
49
0
                        "And 'gdal read <FILENAME> ! ...' as a shortcut for "
50
0
                        "'gdal pipeline <FILENAME> ! ...'.";
51
52
0
    SetDisplayInJSONUsage(false);
53
0
}
54
55
/************************************************************************/
56
/*              GDALMainAlgorithm::ParseCommandLineArguments()          */
57
/************************************************************************/
58
59
bool GDALMainAlgorithm::ParseCommandLineArguments(
60
    const std::vector<std::string> &args)
61
0
{
62
    // Detect shortest form of pipeline:
63
    // "gdal read in.tif ! .... ! write out.tif"
64
0
    if (args.size() >= 2 && args[0] == "read")
65
0
    {
66
0
        m_subAlg =
67
0
            GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate("pipeline");
68
0
        if (m_subAlg)
69
0
        {
70
0
            bool ret = m_subAlg->ParseCommandLineArguments(args);
71
0
            if (ret)
72
0
            {
73
0
                m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm());
74
0
                std::vector<std::string> callPath(m_callPath);
75
0
                callPath.push_back("vector");
76
0
                m_selectedSubAlg->SetCallPath(callPath);
77
0
                return true;
78
0
            }
79
0
            else if (strstr(CPLGetLastErrorMsg(),
80
0
                            "has both raster and vector content"))
81
0
            {
82
0
                m_showUsage = false;
83
0
                return false;
84
0
            }
85
0
        }
86
87
0
        return GDALAlgorithm::ParseCommandLineArguments(args);
88
0
    }
89
0
    else if (args.size() == 1 && args[0].size() >= 2 && args[0][0] == '-' &&
90
0
             args[0][1] == '-')
91
0
    {
92
0
        return GDALAlgorithm::ParseCommandLineArguments(args);
93
0
    }
94
95
    // Generic case: "gdal {subcommand} arguments"
96
    // where subcommand is a known subcommand
97
0
    else if (args.size() >= 1)
98
0
    {
99
0
        const auto nCounter = CPLGetErrorCounter();
100
0
        if (InstantiateSubAlgorithm(args[0]))
101
0
            return GDALAlgorithm::ParseCommandLineArguments(args);
102
0
        if (CPLGetErrorCounter() == nCounter + 1 &&
103
0
            strstr(CPLGetLastErrorMsg(), "Do you mean"))
104
0
        {
105
0
            return false;
106
0
        }
107
0
    }
108
109
    // Otherwise check if that is the shortest form of "gdal read mydataset"
110
    // where "read" is omitted: "gdal in.tif"
111
0
    {
112
0
        VSIStatBufL sStat;
113
0
        for (const auto &arg : args)
114
0
        {
115
0
            if (VSIStatL(arg.c_str(), &sStat) == 0)
116
0
            {
117
0
                m_subAlg =
118
0
                    GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate(
119
0
                        "info");
120
0
                if (m_subAlg)
121
0
                {
122
0
                    bool ret = m_subAlg->ParseCommandLineArguments(args);
123
0
                    if (ret)
124
0
                    {
125
0
                        m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm());
126
0
                        std::vector<std::string> callPath(m_callPath);
127
0
                        callPath.push_back(m_selectedSubAlg->GetArg("layer")
128
0
                                               ? "vector"
129
0
                                               : "raster");
130
0
                        m_selectedSubAlg->SetCallPath(callPath);
131
0
                        return true;
132
0
                    }
133
0
                    else if (strstr(CPLGetLastErrorMsg(),
134
0
                                    "has both raster and vector content"))
135
0
                    {
136
0
                        m_showUsage = false;
137
0
                        return false;
138
0
                    }
139
0
                }
140
0
            }
141
0
        }
142
143
0
        return GDALAlgorithm::ParseCommandLineArguments(args);
144
0
    }
145
0
}
146
147
/************************************************************************/
148
/*                   GDALMainAlgorithm::GetUsageForCLI()                */
149
/************************************************************************/
150
151
std::string
152
GDALMainAlgorithm::GetUsageForCLI(bool shortUsage,
153
                                  const UsageOptions &usageOptions) const
154
0
{
155
0
    if (m_selectedSubAlg)
156
0
        return m_selectedSubAlg->GetUsageForCLI(shortUsage, usageOptions);
157
0
    if (m_showUsage)
158
0
        return GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptions);
159
0
    return std::string();
160
0
}
161
162
/************************************************************************/
163
/*                    GDALMainAlgorithm::RunImpl()                      */
164
/************************************************************************/
165
166
bool GDALMainAlgorithm::RunImpl(GDALProgressFunc, void *)
167
0
{
168
0
    if (m_drivers)
169
0
    {
170
0
        m_output = GDALPrintDriverList(GDAL_OF_KIND_MASK, true);
171
0
    }
172
0
    return true;
173
0
}
174
175
//! @endcond