Coverage Report

Created: 2026-02-14 06:52

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
    {
34
0
        auto &arg = AddArg("source", 0, _("Source dataset name"), &m_source)
35
0
                        .SetPositional()
36
0
                        .SetMinCharCount(0)
37
0
                        .SetRequired();
38
0
        SetAutoCompleteFunctionForFilename(arg, 0);
39
0
    }
40
41
0
    {
42
0
        auto &arg = AddArg("destination", 0, _("Destination dataset name"),
43
0
                           &m_destination)
44
0
                        .SetPositional()
45
0
                        .SetMinCharCount(0)
46
0
                        .SetRequired();
47
0
        SetAutoCompleteFunctionForFilename(arg, 0);
48
0
    }
49
50
0
    AddOverwriteArg(&m_overwrite);
51
52
0
    {
53
0
        auto &arg =
54
0
            AddArg("format", 'f', _("Dataset format"), &m_format)
55
0
                .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_OPEN})
56
0
                .SetCategory(GAAC_ADVANCED);
57
0
        arg.AddValidationAction([this, &arg]()
58
0
                                { return ValidateFormat(arg, false, false); });
59
0
        arg.SetAutoCompleteFunction(
60
0
            [&arg](const std::string &)
61
0
            {
62
0
                return GDALAlgorithm::FormatAutoCompleteFunction(arg, false,
63
0
                                                                 false);
64
0
            });
65
0
    }
66
0
}
67
68
/************************************************************************/
69
/*           GDALDatasetCopyRenameCommonAlgorithm::RunImpl()            */
70
/************************************************************************/
71
72
bool GDALDatasetCopyRenameCommonAlgorithm::RunImpl(GDALProgressFunc, void *)
73
0
{
74
0
    const char *pszType = "";
75
0
    GDALDriver *poDriver = nullptr;
76
0
    if (GDALDoesFileOrDatasetExist(m_destination.c_str(), &pszType, &poDriver))
77
0
    {
78
0
        if (!m_overwrite)
79
0
        {
80
0
            ReportError(CE_Failure, CPLE_AppDefined,
81
0
                        "%s '%s' already exists. Specify the --overwrite "
82
0
                        "option to overwrite it.",
83
0
                        pszType, m_destination.c_str());
84
0
            return false;
85
0
        }
86
0
        else if (EQUAL(pszType, "File"))
87
0
        {
88
0
            VSIUnlink(m_destination.c_str());
89
0
        }
90
0
        else if (EQUAL(pszType, "Directory"))
91
0
        {
92
            // We don't want the user to accidentally erase a non-GDAL dataset
93
0
            ReportError(CE_Failure, CPLE_AppDefined,
94
0
                        "Directory '%s' already exists, but is not "
95
0
                        "recognized as a valid GDAL dataset. "
96
0
                        "Please manually delete it before retrying",
97
0
                        m_destination.c_str());
98
0
            return false;
99
0
        }
100
0
        else if (poDriver)
101
0
        {
102
0
            CPLStringList aosDrivers;
103
0
            aosDrivers.AddString(poDriver->GetDescription());
104
0
            GDALDriver::QuietDelete(m_destination.c_str(), aosDrivers.List());
105
0
        }
106
0
    }
107
108
0
    GDALDriverH hDriver = nullptr;
109
0
    if (!m_format.empty())
110
0
        hDriver = GDALGetDriverByName(m_format.c_str());
111
0
    if (GetName() == GDALDatasetCopyAlgorithm::NAME)
112
0
    {
113
0
        return GDALCopyDatasetFiles(hDriver, m_destination.c_str(),
114
0
                                    m_source.c_str()) == CE_None;
115
0
    }
116
0
    else
117
0
    {
118
0
        return GDALRenameDataset(hDriver, m_destination.c_str(),
119
0
                                 m_source.c_str()) == CE_None;
120
0
    }
121
0
}
122
123
/************************************************************************/
124
/*         GDALDatasetCopyAlgorithm::GDALDatasetCopyAlgorithm()         */
125
/************************************************************************/
126
127
GDALDatasetCopyAlgorithm::GDALDatasetCopyAlgorithm()
128
0
    : GDALDatasetCopyRenameCommonAlgorithm(NAME, DESCRIPTION, HELP_URL)
129
0
{
130
0
}
131
132
0
GDALDatasetCopyAlgorithm::~GDALDatasetCopyAlgorithm() = default;
133
134
//! @endcond