Coverage Report

Created: 2026-07-25 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_dataset_copy.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  gdal "dataset copy" subcommand
5
 * Author:   Even Rouault <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "gdalalg_dataset_copy.h"
14
15
#include "gdal.h"
16
#include "gdal_priv.h"
17
18
//! @cond Doxygen_Suppress
19
20
#ifndef _
21
0
#define _(x) (x)
22
#endif
23
24
/************************************************************************/
25
/*                GDALDatasetCopyRenameCommonAlgorithm()                */
26
/************************************************************************/
27
28
GDALDatasetCopyRenameCommonAlgorithm::GDALDatasetCopyRenameCommonAlgorithm(
29
    const std::string &name, const std::string &description,
30
    const std::string &helpURL)
31
0
    : GDALAlgorithm(name, description, helpURL)
32
0
{
33
0
    AddProgressArg(/* hidden = */ true);
34
35
0
    {
36
0
        auto &arg = AddArg("source", 0, _("Source dataset name"), &m_source)
37
0
                        .SetPositional()
38
0
                        .SetMinCharCount(0)
39
0
                        .SetRequired();
40
0
        SetAutoCompleteFunctionForFilename(arg, 0);
41
0
    }
42
43
0
    {
44
0
        auto &arg = AddArg("destination", 0, _("Destination dataset name"),
45
0
                           &m_destination)
46
0
                        .SetPositional()
47
0
                        .SetMinCharCount(0)
48
0
                        .SetRequired();
49
0
        SetAutoCompleteFunctionForFilename(arg, 0);
50
0
    }
51
52
0
    AddOverwriteArg(&m_overwrite);
53
54
0
    {
55
0
        auto &arg =
56
0
            AddArg("format", 'f', _("Dataset format"), &m_format)
57
0
                .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_OPEN})
58
0
                .SetCategory(GAAC_ADVANCED);
59
0
        arg.AddValidationAction([this, &arg]()
60
0
                                { return ValidateFormat(arg, false, false); });
61
0
        arg.SetAutoCompleteFunction(
62
0
            [&arg](const std::string &)
63
0
            {
64
0
                return GDALAlgorithm::FormatAutoCompleteFunction(arg, false,
65
0
                                                                 false);
66
0
            });
67
0
    }
68
0
}
69
70
/************************************************************************/
71
/*           GDALDatasetCopyRenameCommonAlgorithm::RunImpl()            */
72
/************************************************************************/
73
74
bool GDALDatasetCopyRenameCommonAlgorithm::RunImpl(GDALProgressFunc, void *)
75
0
{
76
0
    const char *pszType = "";
77
0
    GDALDriver *poDriver = nullptr;
78
0
    if (GDALDoesFileOrDatasetExist(m_destination.c_str(), &pszType, &poDriver))
79
0
    {
80
0
        if (!m_overwrite)
81
0
        {
82
0
            ReportError(CE_Failure, CPLE_AppDefined,
83
0
                        "%s '%s' already exists. Specify the --overwrite "
84
0
                        "option to overwrite it.",
85
0
                        pszType, m_destination.c_str());
86
0
            return false;
87
0
        }
88
0
        else if (EQUAL(pszType, "File"))
89
0
        {
90
0
            VSIUnlink(m_destination.c_str());
91
0
        }
92
0
        else if (EQUAL(pszType, "Directory"))
93
0
        {
94
            // We don't want the user to accidentally erase a non-GDAL dataset
95
0
            ReportError(CE_Failure, CPLE_AppDefined,
96
0
                        "Directory '%s' already exists, but is not "
97
0
                        "recognized as a valid GDAL dataset. "
98
0
                        "Please manually delete it before retrying",
99
0
                        m_destination.c_str());
100
0
            return false;
101
0
        }
102
0
        else if (poDriver)
103
0
        {
104
0
            CPLStringList aosDrivers;
105
0
            aosDrivers.AddString(poDriver->GetDescription());
106
0
            GDALDriver::QuietDelete(m_destination.c_str(), aosDrivers.List());
107
0
        }
108
0
    }
109
110
0
    GDALDriverH hDriver = nullptr;
111
0
    if (!m_format.empty())
112
0
        hDriver = GDALGetDriverByName(m_format.c_str());
113
0
    if (GetName() == GDALDatasetCopyAlgorithm::NAME)
114
0
    {
115
0
        return GDALCopyDatasetFiles(hDriver, m_destination.c_str(),
116
0
                                    m_source.c_str()) == CE_None;
117
0
    }
118
0
    else
119
0
    {
120
0
        return GDALRenameDataset(hDriver, m_destination.c_str(),
121
0
                                 m_source.c_str()) == CE_None;
122
0
    }
123
0
}
124
125
/************************************************************************/
126
/*         GDALDatasetCopyAlgorithm::GDALDatasetCopyAlgorithm()         */
127
/************************************************************************/
128
129
GDALDatasetCopyAlgorithm::GDALDatasetCopyAlgorithm()
130
0
    : GDALDatasetCopyRenameCommonAlgorithm(NAME, DESCRIPTION, HELP_URL)
131
0
{
132
0
}
133
134
0
GDALDatasetCopyAlgorithm::~GDALDatasetCopyAlgorithm() = default;
135
136
//! @endcond