KCoreAddons

kbackup.cpp
1 /*
2  This file is part of the KDE libraries
3 
4  SPDX-FileCopyrightText: 1999 Waldo Bastian <[email protected]>
5  SPDX-FileCopyrightText: 2006 Allen Winter <[email protected]>
6  SPDX-FileCopyrightText: 2006 Gregory S. Hayes <[email protected]>
7  SPDX-FileCopyrightText: 2006 Jaison Lee <[email protected]>
8  SPDX-FileCopyrightText: 2011 Romain Perier <[email protected]>
9 
10  SPDX-License-Identifier: LGPL-2.0-only
11 */
12 
13 #include "kbackup.h"
14 
15 #include <QFileInfo>
16 #include <QDir>
17 #include <QProcess>
18 
19 #include <QStandardPaths>
20 
21 namespace KBackup
22 {
23 
24 bool backupFile(const QString &qFilename, const QString &backupDir)
25 {
26  // get backup type from config, by default use "simple"
27  // get extension from config, by default use "~"
28  // get max number of backups from config, by default set to 10
29 #pragma message("KDE5 TODO: Remove KConfig correctly")
30 #if 0
31  KConfigGroup g(KSharedConfig::openConfig(), "Backups"); // look in the Backups section
32  QString type = g.readEntry("Type", "simple");
33  QString extension = g.readEntry("Extension", "~");
34  QString message = g.readEntry("Message", "Automated KDE Commit");
35  int maxnum = g.readEntry("MaxBackups", 10);
36  if (type.toLower() == QLatin1String("numbered")) {
37  return (numberedBackupFile(qFilename, backupDir, extension, maxnum));
38  } else if (type.toLower() == QLatin1String("rcs")) {
39  return (rcsBackupFile(qFilename, backupDir, message));
40  } else {
41  return (simpleBackupFile(qFilename, backupDir, extension));
42  }
43 #endif
44  return (simpleBackupFile(qFilename, backupDir, QStringLiteral("~")));
45 }
46 
47 bool simpleBackupFile(const QString &qFilename,
48  const QString &backupDir,
49  const QString &backupExtension)
50 {
51  QString backupFileName = qFilename + backupExtension;
52 
53  if (!backupDir.isEmpty()) {
54  QFileInfo fileInfo(qFilename);
55  backupFileName = backupDir + QLatin1Char('/') + fileInfo.fileName() + backupExtension;
56  }
57 
58 // qCDebug(KCOREADDONS_DEBUG) << "KBackup copying " << qFilename << " to " << backupFileName;
59  QFile::remove(backupFileName);
60  return QFile::copy(qFilename, backupFileName);
61 }
62 
63 bool rcsBackupFile(const QString &qFilename,
64  const QString &backupDir,
65  const QString &backupMessage)
66 {
67  QFileInfo fileInfo(qFilename);
68 
69  QString qBackupFilename;
70  if (backupDir.isEmpty()) {
71  qBackupFilename = qFilename;
72  } else {
73  qBackupFilename = backupDir + fileInfo.fileName();
74  }
75  qBackupFilename += QLatin1String(",v");
76 
77  // If backupDir is specified, copy qFilename to the
78  // backupDir and perform the commit there, unlinking
79  // backupDir/qFilename when finished.
80  if (!backupDir.isEmpty()) {
81  if (!QFile::copy(qFilename, backupDir + fileInfo.fileName())) {
82  return false;
83  }
84  fileInfo.setFile(backupDir + QLatin1Char('/') + fileInfo.fileName());
85  }
86 
87  const QString cipath = QStandardPaths::findExecutable(QStringLiteral("ci"));
88  const QString copath = QStandardPaths::findExecutable(QStringLiteral("co"));
89  const QString rcspath = QStandardPaths::findExecutable(QStringLiteral("rcs"));
90  if (cipath.isEmpty() || copath.isEmpty() || rcspath.isEmpty()) {
91  return false;
92  }
93 
94  // Check in the file unlocked with 'ci'
95  QProcess ci;
96  if (!backupDir.isEmpty()) {
97  ci.setWorkingDirectory(backupDir);
98  }
99  ci.start(cipath, QStringList { QStringLiteral("-u"), fileInfo.filePath() });
100  if (!ci.waitForStarted()) {
101  return false;
102  }
103  ci.write(backupMessage.toLocal8Bit());
104  ci.write(".");
105  ci.closeWriteChannel();
106  if (!ci.waitForFinished()) {
107  return false;
108  }
109 
110  // Use 'rcs' to unset strict locking
111  QProcess rcs;
112  if (!backupDir.isEmpty()) {
113  rcs.setWorkingDirectory(backupDir);
114  }
115  rcs.start(rcspath, QStringList { QStringLiteral("-U"), qBackupFilename });
116  if (!rcs.waitForFinished()) {
117  return false;
118  }
119 
120  // Use 'co' to checkout the current revision and restore permissions
121  QProcess co;
122  if (!backupDir.isEmpty()) {
123  co.setWorkingDirectory(backupDir);
124  }
125  co.start(copath, QStringList { qBackupFilename });
126  if (!co.waitForFinished()) {
127  return false;
128  }
129 
130  if (!backupDir.isEmpty()) {
131  return QFile::remove(fileInfo.filePath());
132  } else {
133  return true;
134  }
135 }
136 
137 bool numberedBackupFile(const QString &qFilename,
138  const QString &backupDir,
139  const QString &backupExtension,
140  const uint maxBackups)
141 {
142  QFileInfo fileInfo(qFilename);
143 
144  // The backup file name template.
145  QString sTemplate;
146  if (backupDir.isEmpty()) {
147  sTemplate = qFilename + QLatin1String(".%1") + backupExtension;
148  } else {
149  sTemplate = backupDir + QLatin1Char('/') + fileInfo.fileName() + QLatin1String(".%1") + backupExtension;
150  }
151 
152  // First, search backupDir for numbered backup files to remove.
153  // Remove all with number 'maxBackups' and greater.
154  QDir d = backupDir.isEmpty() ? fileInfo.dir() : backupDir;
156  const QStringList nameFilters = QStringList(fileInfo.fileName() + QLatin1String(".*") + backupExtension);
157  d.setNameFilters(nameFilters);
159 
160  uint maxBackupFound = 0;
161  const QFileInfoList infoList = d.entryInfoList();
162  for (const QFileInfo &fi : infoList) {
163  if (fi.fileName().endsWith(backupExtension)) {
164  // sTemp holds the file name, without the ending backupExtension
165  QString sTemp = fi.fileName();
166  sTemp.truncate(fi.fileName().length() - backupExtension.length());
167  // compute the backup number
168  int idex = sTemp.lastIndexOf(QLatin1Char('.'));
169  if (idex > 0) {
170  bool ok;
171  uint num = sTemp.midRef(idex + 1).toUInt(&ok);
172  if (ok) {
173  if (num >= maxBackups) {
174  QFile::remove(fi.filePath());
175  } else {
176  maxBackupFound = qMax(maxBackupFound, num);
177  }
178  }
179  }
180  }
181  }
182 
183  // Next, rename max-1 to max, max-2 to max-1, etc.
184  QString to = sTemplate.arg(maxBackupFound + 1);
185  for (int i = maxBackupFound; i > 0; i--) {
186  QString from = sTemplate.arg(i);
187 // qCDebug(KCOREADDONS_DEBUG) << "KBackup renaming " << from << " to " << to;
188  QFile::rename(from, to);
189  to = from;
190  }
191 
192  // Finally create most recent backup by copying the file to backup number 1.
193 // qCDebug(KCOREADDONS_DEBUG) << "KBackup copying " << qFilename << " to " << sTemplate.arg(1);
194  return QFile::copy(qFilename, sTemplate.arg(1));
195 }
196 
197 }
bool backupFile(const QString &qFilename, const QString &backupDir)
Function to create a backup file before saving.
Definition: kbackup.cpp:24
void truncate(int position)
void setNameFilters(const QStringList &nameFilters)
bool remove()
void setFile(const QString &file)
bool rename(const QString &newName)
QString findExecutable(const QString &executableName, const QStringList &paths)
bool rcsBackupFile(const QString &qFilename, const QString &backupDir, const QString &backupMessage)
Function to create an rcs backup file for a given filename.
Definition: kbackup.cpp:63
void setSorting(QDir::SortFlags sort)
bool copy(const QString &newName)
bool numberedBackupFile(const QString &qFilename, const QString &backupDir, const QString &backupExtension, const uint maxBackups)
Function to create a backup file for a given filename.
Definition: kbackup.cpp:137
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString filePath() const const
Provides utility functions for backup of files.
Definition: kbackup.cpp:21
void setFilter(QDir::Filters filters)
QString fileName() const const
QFileInfoList entryInfoList(QDir::Filters filters, QDir::SortFlags sort) const const
bool isEmpty() const const
QDir dir() const const
QString toLower() const const
QByteArray toLocal8Bit() const const
bool waitForStarted(int msecs)
void setWorkingDirectory(const QString &dir)
QStringRef midRef(int position, int n) const const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
bool simpleBackupFile(const QString &qFilename, const QString &backupDir, const QString &backupExtension)
Function to create a backup file for a given filename.
Definition: kbackup.cpp:47
uint toUInt(bool *ok, int base) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int length() const const
qint64 write(const char *data, qint64 maxSize)
void closeWriteChannel()
T readEntry(const QString &key, const T &aDefault) const
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode)
bool waitForFinished(int msecs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jul 13 2020 23:01:57 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.