29235e3650082a1a9a35c68ec5e074ca6f29e51d
2 * Copyright (C) 2007 Thiago Macieira <thiago@kde.org>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "repository.h"
19 #include <QTextStream>
22 Repository::Repository(const Rules::Repository
&rule
)
23 : name(rule
.name
), commitCount(0), processHasStarted(false)
25 foreach (Rules::Repository::Branch branchRule
, rule
.branches
) {
27 branch
.created
= 0; // not created
29 branches
.insert(branchRule
.name
, branch
);
32 // create the default branch
33 branches
["master"].created
= 1;
35 fastImport
.setWorkingDirectory(name
);
38 Repository::~Repository()
40 if (fastImport
.state() != QProcess::NotRunning
) {
41 fastImport
.write("checkpoint\n");
42 fastImport
.waitForBytesWritten(-1);
43 fastImport
.closeWriteChannel();
44 if (!fastImport
.waitForFinished()) {
45 fastImport
.terminate();
46 if (!fastImport
.waitForFinished(200))
47 qWarning() << "git-fast-import for repository" << name
<< "did not die";
52 void Repository::reloadBranches()
55 revParse
.setWorkingDirectory(name
);
56 revParse
.start("git", QStringList() << "rev-parse" << "--symbolic" << "--branches");
57 revParse
.waitForFinished();
59 if (revParse
.exitCode() == 0 && revParse
.bytesAvailable()) {
62 while (revParse
.canReadLine()) {
63 QByteArray branchName
= revParse
.readLine().trimmed();
65 branches
[branchName
].created
= 1;
66 fastImport
.write("reset refs/heads/" + branchName
+
67 "\nfrom refs/heads/" + branchName
+ "^0\n\n");
72 void Repository::createBranch(const QString
&branch
, int revnum
,
73 const QString
&branchFrom
, int)
75 if (!branches
.contains(branch
)) {
76 qWarning() << branch
<< "is not a known branch in repository" << name
<< endl
77 << "Going to create it automatically";
81 QByteArray branchRef
= branch
.toUtf8();
82 if (!branchRef
.startsWith("refs/"))
83 branchRef
.prepend("refs/heads/");
85 Branch
&br
= branches
[branch
];
86 if (br
.created
&& br
.created
!= revnum
) {
87 QByteArray backupBranch
= branchRef
+ '_' + QByteArray::number(revnum
);
88 qWarning() << branch
<< "already exists; backing up to" << backupBranch
;
90 fastImport
.write("reset " + backupBranch
+ "\nfrom " + branchRef
+ "\n\n");
93 // now create the branch
95 QByteArray branchFromRef
= branchFrom
.toUtf8();
96 if (!branchFromRef
.startsWith("refs/"))
97 branchFromRef
.prepend("refs/heads/");
99 if (!branches
.contains(branchFrom
) || !branches
.value(branchFrom
).created
) {
100 qCritical() << branch
<< "in repository" << name
101 << "is branching from branch" << branchFrom
102 << "but the latter doesn't exist. Can't continue.";
106 fastImport
.write("reset " + branchRef
+ "\nfrom " + branchFromRef
+ "\n\n");
109 Repository::Transaction
*Repository::newTransaction(const QString
&branch
, const QString
&svnprefix
,
112 if (!branches
.contains(branch
)) {
113 qWarning() << branch
<< "is not a known branch in repository" << name
<< endl
114 << "Going to create it automatically";
117 Transaction
*txn
= new Transaction
;
118 txn
->repository
= this;
119 txn
->branch
= branch
.toUtf8();
120 txn
->svnprefix
= svnprefix
.toUtf8();
122 txn
->revnum
= revnum
;
123 txn
->lastmark
= revnum
;
126 if ((++commitCount
% 10000) == 0)
127 // write everything to disk every 10000 commits
128 fastImport
.write("checkpoint\n");
132 void Repository::startFastImport()
134 if (fastImport
.state() == QProcess::NotRunning
) {
135 if (processHasStarted
)
136 qFatal("git-fast-import has been started once and crashed?");
137 processHasStarted
= true;
140 QString outputFile
= name
;
141 outputFile
.replace('/', '_');
142 outputFile
.prepend("log-");
143 fastImport
.setStandardOutputFile(outputFile
, QIODevice::Append
);
144 fastImport
.setProcessChannelMode(QProcess::MergedChannels
);
147 fastImport
.start("git-fast-import", QStringList());
149 fastImport
.start("/bin/cat", QStringList());
154 Repository::Transaction::~Transaction()
158 void Repository::Transaction::setAuthor(const QByteArray
&a
)
163 void Repository::Transaction::setDateTime(uint dt
)
168 void Repository::Transaction::setLog(const QByteArray
&l
)
173 void Repository::Transaction::deleteFile(const QString
&path
)
175 deletedFiles
.append(path
);
178 QIODevice
*Repository::Transaction::addFile(const QString
&path
, int mode
, qint64 length
)
182 fp
.mark
= ++lastmark
;
185 repository
->fastImport
.write("blob\nmark :");
186 repository
->fastImport
.write(QByteArray::number(fp
.mark
));
187 repository
->fastImport
.write("\ndata ");
188 repository
->fastImport
.write(QByteArray::number(length
));
189 repository
->fastImport
.write("\n", 1);
192 modifiedFiles
.insert(path
, fp
);
193 return &repository
->fastImport
;
196 void Repository::Transaction::commit()
198 // create the commit message
199 QByteArray message
= log
;
200 if (!message
.endsWith('\n'))
202 message
+= "\nsvn path=" + svnprefix
+ "; revision=" + QByteArray::number(revnum
) + "\n";
205 QByteArray branchRef
= branch
;
206 if (!branchRef
.startsWith("refs/"))
207 branchRef
.prepend("refs/heads/");
209 QTextStream
s(&repository
->fastImport
);
210 s
<< "commit " << branchRef
<< endl
;
211 s
<< "mark :" << revnum
<< endl
;
212 s
<< "committer " << QString::fromUtf8(author
) << ' ' << datetime
<< " -0000" << endl
;
214 Branch
&br
= repository
->branches
[branch
];
216 qWarning() << "Branch" << branch
<< "in repository" << repository
->name
<< "doesn't exist at revision"
217 << revnum
<< "-- did you resume from the wrong revision?";
221 s
<< "data " << message
.length() << endl
;
224 repository
->fastImport
.write(message
);
225 repository
->fastImport
.putChar('\n');
227 // write the file deletions
228 if (deletedFiles
.contains(""))
229 repository
->fastImport
.write("deleteall\n");
231 foreach (QString df
, deletedFiles
)
232 repository
->fastImport
.write("D " + df
.toUtf8() + "\n");
234 // write the file modifications
235 QHash
<QString
, FileProperties
>::ConstIterator it
= modifiedFiles
.constBegin();
236 for ( ; it
!= modifiedFiles
.constEnd(); ++it
) {
237 repository
->fastImport
.write("M ", 2);
238 repository
->fastImport
.write(QByteArray::number(it
->mode
, 8));
239 repository
->fastImport
.write(" :", 2);
240 repository
->fastImport
.write(QByteArray::number(it
->mark
));
241 repository
->fastImport
.write(" ", 1);
242 repository
->fastImport
.write(it
.key().toUtf8());
243 repository
->fastImport
.write("\n", 1);
246 repository
->fastImport
.write("\n");
248 while (repository
->fastImport
.bytesToWrite())
249 if (!repository
->fastImport
.waitForBytesWritten(-1))
250 qFatal("Failed to write to process: %s", qPrintable(repository
->fastImport
.errorString()));