[PATCH qgit] Add support for --early-output option of git log command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With this option 'git log' outputs the first commits
as soon as they are ready in order to be able to show at
least something quickly, even if the full output may take
longer to generate.

At the end of the reordering correct revisions are re-sent.

This avoid the user to wait in front a blank screen for
several seconds in case of big repos and cold chaches.

STGit repositories are still not correctly handled, and
file history (annotation) does not uses, still, this new
--early-output feature.

Signed-off-by: Marco Costalba <mcostalba@xxxxxxxxx>
---

Patch to apply on top of current qgit-2.0 at

git://git.kernel.org/pub/scm/qgit/qgit4.git


 src/common.h        |    2 +-
 src/git.cpp         |   12 ++++++++----
 src/git.h           |    3 ++-
 src/git_startup.cpp |   39 +++++++++++++++----
 4 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/src/common.h b/src/common.h
index 198348e..de3cb7d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -289,7 +289,7 @@ namespace QGit {
 class Rev {
 	// prevent implicit C++ compiler defaults
 	Rev();
-	Rev(const Rev&);
+// 	Rev(const Rev&);
 	Rev& operator=(const Rev&);
 public:
 	Rev(const QByteArray& b, uint s, int idx, int* next, bool withDiff)
diff --git a/src/git.cpp b/src/git.cpp
index d273c60..ef9b627 100644
--- a/src/git.cpp
+++ b/src/git.cpp
@@ -73,9 +73,11 @@ const QString FileHistory::sha(int row) const {
 	return (row < 0 || row >= _rowCnt ? "" : revOrder.at(row));
 }

-void FileHistory::clear() {
+void FileHistory::clear(bool earlyOutput) {
+
+	if (!earlyOutput)
+		git->cancelDataLoading(this);

-	git->cancelDataLoading(this);
 	qDeleteAll(revs);
 	revs.clear();
 	revOrder.clear();
@@ -83,9 +85,11 @@ void FileHistory::clear() {
 	lns->clear();
 	fNames.clear();
 	curFNames.clear();
-	qDeleteAll(rowData);
-	rowData.clear();

+	if (!earlyOutput) {
+		qDeleteAll(rowData);
+		rowData.clear();
+	}
 	if (testFlag(REL_DATE_F)) {
 		_secs = QDateTime::currentDateTime().toTime_t();
 		_headerInfo[4] = "Last Change";
diff --git a/src/git.h b/src/git.h
index de014e0..92879fb 100644
--- a/src/git.h
+++ b/src/git.h
@@ -27,7 +27,7 @@ Q_OBJECT
 public:
 	FileHistory(QObject* parent, Git* git);
 	~FileHistory();
-	void clear();
+	void clear(bool earlyOutput = false);
 	const QString sha(int row) const;
 	int row(SCRef sha) const;
 	const QStringList fileNames() const { return fNames; }
@@ -251,6 +251,7 @@ private:
 	bool startParseProc(SCList initCmd, FileHistory* fh, SCRef buf);
 	bool tryFollowRenames(FileHistory* fh);
 	bool populateRenamedPatches(SCRef sha, SCList nn, FileHistory* fh,
QStringList* on, bool bt);
+	void doEarlyOutput(Rev* rev, int* start);
 	int addChunk(FileHistory* fh, const QByteArray& ba, int ofs);
 	void parseDiffFormat(RevFile& rf, SCRef buf);
 	void parseDiffFormatLine(RevFile& rf, SCRef line, int parNum);
diff --git a/src/git_startup.cpp b/src/git_startup.cpp
index 3faa059..df272fc 100644
--- a/src/git_startup.cpp
+++ b/src/git_startup.cpp
@@ -492,7 +492,9 @@ bool Git::startRevList(SCList args, FileHistory* fh) {
 	   the file deletion revision.
 	*/
 		initCmd << QString("-r -m -p --full-index").split(' ');
-	}
+	} else
+		initCmd << QString("--early-output");
+
 	return startParseProc(initCmd + args, fh, QString());
 }

@@ -839,13 +841,38 @@ void Git::loadFileNames() {
 	indexTree();
 }

+void Git::doEarlyOutput(Rev* rev, int* start) {
+
+	delete rev;
+	*start += QString("Final output:\n").length();
+
+	Rev* cl = NULL;
+	const Rev* r = revLookup(ZERO_SHA);
+	if (r)
+		cl = new Rev(*r); // copy working dir revision
+
+	revData->clear(true); // keep row QByteArray data
+
+	if (cl) { // re-add working dir revision
+		revData->revs.insert(ZERO_SHA, cl);
+		revData->revOrder.append(ZERO_SHA);
+	}
+}
+
 int Git::addChunk(FileHistory* fh, const QByteArray& ba, int start) {

 	RevMap& r = fh->revs;
 	int nextStart;
+	Rev* rev;

-	// only here we create a new rev
-	Rev* rev = new Rev(ba, start, fh->revOrder.count(), &nextStart,
!isMainHistory(fh));
+	do {
+		// only here we create a new rev
+		rev = new Rev(ba, start, fh->revOrder.count(), &nextStart,
!isMainHistory(fh));
+
+		if (nextStart == -2)
+			doEarlyOutput(rev, &start);
+
+	} while (nextStart == -2);

 	if (nextStart == -1) { // half chunk detected
 		delete rev;
@@ -1331,6 +1358,7 @@ int Rev::indexData(bool quick, bool withDiff) const {
 /*
   This is what 'git log' produces:

+	- a possible one line with "Final output:\n" in case of --early-output option
 	- one line with "commit" + sha + an arbitrary amount of parent's sha, in case
 	  of a merge in file history the line terminates with "(from <sha of parent>)"
 	- one line with "log size" + len of this record
@@ -1346,9 +1374,12 @@ int Rev::indexData(bool quick, bool withDiff) const {
 	- a terminating '\0'
 */
 	int last = ba.size() - 1;
-	if (start > last)
+	if (start > last) // offset 'start' points to the char after "commit "
 		return -1;

+	if (uint(ba.at(start) == 'u'))
+		return -2; // "Final output:", let caller handle this
+
 	// take in account --boundary and --left-right options
 	startOfs = uint(ba.at(start) == '-' || ba.at(start) == '<' ||
ba.at(start) == '>');
 	boundary = startOfs && ba.at(start) == '-';
-- 
1.5.3.5.532.g5c38-dirty
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux