Find commits on one branch that aren't on another with JGit - jgit

I'm trying to find commits on branch foo that aren't on master. I have this working for the simple cases, but once new changes have been merged from master into foo it breaks down.
In more detail:
If you have commits A, B, and C on master
then you create branch foo and add commits D and E there
then you create commit F on master
then you merge F from master into foo (using a merge commit)
now trying to get the merge base returns F instead of C. So I can't iterate over commits from C to foo's head (giving C, D, E, F, which I'll then narrow down to D & E using isMergedInto)
public RevCommit findMergeBase(ObjectId foo, ObjectId bar) throws MissingObjectException,
IncorrectObjectTypeException, IOException {
RevWalk walk = null;
try {
walk = new RevWalk(repo);
RevCommit fooHead = walk.parseCommit(foo);
RevCommit barHead = walk.parseCommit(bar);
walk.setRevFilter(RevFilter.MERGE_BASE);
walk.markStart(fooHead);
walk.markStart(barHead);
RevCommit base = null;
while (true) {
RevCommit commit = walk.next();
if (commit == null)
break;
base = commit;
}
return base;
}
finally {
if (walk != null) {
walk.reset();
walk.close();
walk.dispose();
}
}
}

Seems like the issue may have been that I created by feature branch off of the remote master branch? So it couldn't figure out how the feature branch connected to my local master? Once I updated my local master branch it worked as expected.

Related

How to get the changed files list for a commit with JGit

I want to get the changed files between two commits, not the diff information, how can I use JGit to make it?
With two refs pointing at the two commits it should suffice to do the following to iterate all changes between the commits:
ObjectId oldHead = repository.resolve("HEAD^^^^{tree}");
ObjectId head = repository.resolve("HEAD^{tree}");
// prepare the two iterators to compute the diff between
try (ObjectReader reader = repository.newObjectReader()) {
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
oldTreeIter.reset(reader, oldHead);
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
newTreeIter.reset(reader, head);
// finally get the list of changed files
try (Git git = new Git(repository)) {
List<DiffEntry> diffs= git.diff()
.setNewTree(newTreeIter)
.setOldTree(oldTreeIter)
.call();
for (DiffEntry entry : diffs) {
System.out.println("Entry: " + entry);
}
}
}
}
There is a ready-to-run example snippet contained in the jgit-cookbook

Modified function not working as intended without recursion

I have a recursive function which iterates though directory trees listing the file names located in them.
Here is the function:
void WINAPI SearchFile(PSTR Directory)
{
HANDLE hFind;
WIN32_FIND_DATA FindData;
char SearchName[1024],FullPath[1024];
memset(SearchName,0,sizeof(SearchName));
memset(&FindData,0,sizeof(WIN32_FIND_DATA));
sprintf(SearchName,"%s\\*",Directory);
hFind=FindFirstFile(SearchName,&FindData);
if(hFind!=INVALID_HANDLE_VALUE)
{
while(FindNextFile(hFind,&FindData))
{
if(FindData.cFileName[0]=='.')
{
continue;
}
memset(FullPath,0,sizeof(FullPath));
sprintf(FullPath,"%s\\%s",Directory,FindData.cFileName);
if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
MessageBoxA(NULL, FullPath, "Directory", MB_OK);
SearchFile(FullPath);
}
else
{
MessageBoxA(NULL, FullPath, "File", MB_OK);
}
}
FindClose(hFind);
}
}
There are obviously differences between both functions but I don't understand what's making them act differently. Does anyone know why I am having this problem?
for fast understand error need look for line
goto label;
//SearchFile(FullPath);
at this point hFind containing valid data and FindClose(hFind); need be called for it. but after goto label; executed - your overwrite hFind with hFind = FindFirstFile(SearchName, &FindData); - so you already never close original hFind, never can return to iterate folder after such go to sub-folder. this is key point - need save original hFind before go to sub directory and restore it after. when you do recursive function call - this is done auto - because every sub directory in this case enumerated in self stack frame, which have separate hFind. this is native solution use recursion here.
but possible convert recursion to loop here because we call self always from the single place and as result to this single place. so we can not save return address in stack but do unconditional jump (goto) to known place.
then code have some extra errors, you never check for string buffers overflow, why 1024 as max length is hard-coded when file path can be up to 32768 chars, you not check for reparse point as result can enter to infinite loop, use FindFirstFile instead FindFirstFileEx, etc.
correct code for enumerate sub-folder in loop can be next
void DoEnum(PCWSTR pcszRoot)
{
SIZE_T FileNameLength = wcslen(pcszRoot);
// initial check for . and ..
switch (FileNameLength)
{
case 2:
if (pcszRoot[1] != '.') break;
case 1:
if (pcszRoot[0] == '.') return;
}
static const WCHAR mask[] = L"\\*";
WCHAR FileName[MAXSHORT + 1];
if (_countof(FileName) < FileNameLength + _countof(mask))
{
return;
}
ULONG dwError;
HANDLE hFindFile = 0;
WIN32_FIND_DATA FindData{};
enum { MaxDeep = 0x200 };
//++ stack
HANDLE hFindFileV[MaxDeep];
PWSTR pszV[MaxDeep];
char prefix[MaxDeep+1];
//--stack
ULONG Level = MaxDeep;
memset(prefix, '\t', MaxDeep);
prefix[MaxDeep] = 0;
PWSTR psz = FileName;
goto __enter;
__loop:
hFindFile = FindFirstFileEx(FileName, FindExInfoBasic, &FindData, FindExSearchNameMatch, 0, FIND_FIRST_EX_LARGE_FETCH);
if (hFindFile != INVALID_HANDLE_VALUE)
{
do
{
pcszRoot = FindData.cFileName;
// skip . and ..
switch (FileNameLength = wcslen(pcszRoot))
{
case 2:
if (pcszRoot[1] != '.') break;
case 1:
if (pcszRoot[0] == '.') continue;
}
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((SIZE_T)(FileName + _countof(FileName) - psz) < FileNameLength + _countof(mask))
{
continue;
}
__enter:
memcpy(psz, pcszRoot, (1 + FileNameLength) * sizeof(WCHAR));
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
DbgPrint("%sreparse point: <%S>\n", prefix + Level, pcszRoot);
}
else
{
if (Level)
{
DbgPrint("%s<%S>\n", prefix + Level, psz);
hFindFileV[--Level] = hFindFile;
pszV[Level] = psz;
memcpy(psz += FileNameLength, mask, sizeof(mask));
psz++;
goto __loop;
__return:
*--psz = 0;
psz = pszV[Level];
hFindFile = hFindFileV[Level++];
DbgPrint("%s</%S>\n", prefix + Level, psz);
}
}
}
else
{
DbgPrint("%s[%u%u] %S\n", prefix + Level, FindData.nFileSizeLow, FindData.nFileSizeHigh, pcszRoot);
}
if (!hFindFile)
{
// top level exit
return ;
}
} while (FindNextFile(hFindFile, &FindData));
if ((dwError = GetLastError()) == ERROR_NO_MORE_FILES)
{
dwError = NOERROR;
}
FindClose(hFindFile);
}
else
{
dwError = GetLastError();
}
if (dwError)
{
DbgPrint("<%S> err = %u\n", FileName, dwError);
}
goto __return;
}
The reason for the difference is actually the confusion brought to you by goto label.If you are using the recursive version, after the recursive execution is completed, it will return to the recursive place to continue execution.
In your code, you continue to execute while (FindNextFile(hFind, &FindData)), but when you use goto label, it will jump out of the original loop and restart the program from the label, which leads to what you said list a single directory tree before ending.
If you modify the modified code to the following iterative version, you can understand why there is such a problem.
void fun()
{
char* Directory = "D:\\test";
HANDLE hFind;
WIN32_FIND_DATA FindData;
char SearchName[1024], FullPath[1024];
char LastName[1024] = "";
while (1)
{
memset(SearchName, 0, sizeof(SearchName));
memset(&FindData, 0, sizeof(WIN32_FIND_DATA));
sprintf(SearchName, "%s\\*", Directory);
if (strcmp(SearchName, LastName) == 0)
{
return;
}
strcpy(LastName, SearchName);
hFind = FindFirstFile(SearchName, &FindData);
if (hFind != INVALID_HANDLE_VALUE)
{
while (FindNextFile(hFind, &FindData))
{
if (FindData.cFileName[0] == '.')
{
continue;
}
memset(FullPath, 0, sizeof(FullPath));
sprintf(FullPath, "%s\\%s", Directory, FindData.cFileName);
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
MessageBoxA(NULL, Directory, "Directory", MB_OK);
char cArray[1024];
memset(cArray, 0, sizeof(cArray));
sprintf(cArray, "%s", FullPath);
Directory = cArray;
break;
}
else
{
MessageBoxA(NULL, FullPath, "File", MB_OK);
}
}
FindClose(hFind);
}
}
}
So you cannot achieve the same purpose as recursion by using goto, here you can only use recursion. Of course, I have provided a way to traverse directories non-recursively using queues, which is a more scientific way.
One of the key things that you obtain from recursion is a separate set of local variables for each call to the recursive function. When a function calls itself, and in the recursive call modifies local variables, those local-variable changes do not (directly) affect the local variables of the caller. In your original program, this applies to variables hFind, FindData, SearchName, and FullPath.
If you want similar behavior in a non-recursive version of the function then you need to manually preserve the state of your traversal of one level of the tree when you descend to another level. The goto statement doesn't do any such thing -- it just redirects the control flow of your program. Although there are a few good use cases for goto in C, they are uncommon, and yours is not one of them.
There are several ways to implement manually preserving state, but I would suggest
creating a structure type in which to store those data that characterize the state of your traversal of a particular level. Those appear to be only hFind and FindData -- it looks like the other locals don't need to be preserved. Maybe something like this, then:
struct dir_state {
HANDLE hFind;
WIN32_FIND_DATA FindData;
};
Dynamically allocating an array of structures of that type.
unsigned depth_limit = DEFAULT_DEPTH_LIMIT;
struct dir_state *traversal_states
= malloc(depth_limit * sizeof(*traversal_states));
if (traversal_states == NULL) // ... handle allocation error ...
Tracking the depth of your tree traversal, and for each directory you process, using the array element whose index is the relative depth of that directory.
// For example:
traversal_states[depth].hFind
= FindFirstFile(SearchName, &traversal_states[depth].FindData);
// etc.
Remembering the size of the array, so as to be able to reallocate it larger if the traversal descends too deep for its current size.
// For example:
if (depth >= depth_limit) {
depth_limit = depth_limit * 3 / 2;
struct dir_state *temp
= realloc(traversal_states, depth_limit * sizeof(*traversal_states));
if (temp == NULL) {
// handle error, discontinuing traversal
}
traversal_states = temp;
}
Also, use an ordinary for, while, or do loop instead of a backward-jumping goto. There will be a few details to work out to track when to use FindFirstFile and when FindNextFile (which you would still have with goto), but I'm sure you can sort it out.
Details are left as an exercise.
Unless necessary due to memory or processing constraints or infinite recursion tail conditions that would be complication to introduce there really isn't much need to not use recursion here, since it leads to a readable and elegant solution.
I also want to point out that in "modern" C, any solution using a GOTO is likely not a solution you want since they are so often confusing to use and leads to memory issues (we have loops now to make all of that so much simpler).
Instead of the GOTOs I would suggest implementing a stack of the directories. Wrap the printing logic a while or do-while, and as you are iterating over the files add any directories to the stack. At every new iteration pop and walk the directory at the head of the stack. The loop condition just needs to check if the directory stack is empty, before continuing its block.

Is it possible to add new CompletableFutures to CompletableFuture.allOf() dynamically?

I have a database with 3 tables:
Table A which contains data of A objects
Table B which contains data of B objects
Table C which contains data of C objects
A objects can have 0 or 1 B objects
B objects can have 0 or 1 C objects
(I know, these could be in just one table, but its just for the example)
I want to make a csv file from the whole database:
each line should contain exactly one A object, optionally its B object, and optionally its C object.
For each table there is an asynchronous repository, that gives back a CompletionStage. So when I fetch A objects from the repositoryA, I get back a CompletionStage<List<A>>. When it completes, I make a Map for every A object, fill it with the data of A and I call the repositoryB.getB(A.id) , which gives back a CompletionStage<Optional<B>>. If the B value is not present, I append a new line to my CSV file with the data inside of the map. If the B is present, I add its values to the map, and call repositoryC.getC(B.id) which returns a CompletionStage<Optional<C>>. If the C is present, I add its values to the Map, and add a new line to the CSV file, if it is not, then I just add the new line.
The creation of the CSV is done, when all CompletionStages are completed. I tried to use the CompletableFuture.allOf(), but since at the beginning i don't know how many CompletionStages there will be, I can't add all of them to the allOf method, so I think i would need to add the Completionstages dynamically somehow. Is it possible?
Currently I have a working solution, but it blocks after every B and C fetch, so I want to make the whole code nonblocking.
This is my nonblocking attempt, but its not working well, as some of the B and C futures aren't added to the list of futures, so the code does not wait for their completion:
CompletableFuture<List<CompletableFuture>> genereteCSV = repositoryA.getAs().thenApplyAsync(listA-> {
List<CompletableFuture> futures = new ArrayList<>();
for (A a : listA) {
Map<String, String> values = new Map<>();
addAvaluesToMap(values, A);
CompletableFuture Bfuture = repositoryB.getB(A.id).thenAcceptAsync((optionalB -> {
if (optionalB.isPresent()) {
addValuesToMap(values, B);
CompletableFuture Cfuture = repositoryC.getC(B.id).thenAcceptAsync(optionalC-> {
if (optionalC.isPresent()) {
addAvaluesToMap(values, C);
}
addMapValuesToCSV(values);
});
futures.add(Cfuture);
} else {
addMapValuesToCSV(values);
}
}));
futures.add(Bfuture);
}
return futures;
});
geerateCSV.thenApplyAsync(futureList-> CompletableFuture.allOf(futureList.toArray(new CompletableFuture<?>[0])))
.thenAccept(dummy->{System.out.println("CsV generation done");});
Basically, this is one possible plan to achieve non-blocking processing:
Create CompletableFuture for each object A (possibly populated
with B and C objects)
Asynchronously gather A objects from CompletableFutures
Write created A objects to CSV file
Notes: In the example below I've used addAvaluesToMap and addMapValuesToCSV assuming, that you have them working. Also, I assume, that your usage of CompletableFutures is justified by your goals.
This will be an implementation of approach described above:
public void generateCSV() {
repositoryA.getAs().thenAccept(listA -> {
List<CompletableFuture<A>> futures = listA.stream()
.map(a -> repositoryB.getB(a.id).thenComposeAsync(optionalB ->
optionalB.map(b -> repositoryC.getC(b.id).thenComposeAsync(optionalC -> {
a.setB(b);
return optionalC.map(c -> {
b.setC(c);
return CompletableFuture.completedFuture(a);
}).orElse(CompletableFuture.completedFuture(a));
})
).orElse(CompletableFuture.completedFuture(a)))
).collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
.thenAccept(v -> futures.stream()
.map(CompletableFuture::join)
.forEach(a -> {
Map<String, String> values = new HashMap<>();
addAvaluesToMap(values, a);
addMapValuesToCSV(values);
})
)
.exceptionally(throwable -> {
System.out.println("Failed generating CSV. Error: " + throwable);
return null;
});
}).exceptionally(throwable -> {
System.out.println("Failed to get list of As. Error: " + throwable);
return null;
});
}
You are using a relational database. It should be easier and more performant to write a database query to return the data you want in the format you need than to write this in java. An SQL query will allow you to join three tables together very easily and provide the results in a format which can easily be extracted in csv format. Databases can perform these operations much more effectively than by writing your own implementation.

Robot Framework: Timed out waiting for page load

We have run our Robot Framework environment nearly one year without any problems, but now we get the error message:
TimeoutException: Message: Timed out waiting for page load.
Stacktrace:
at Utils.initWebLoadingListener/< (file:///tmp/tmp77bOby/webdriver-py-profilecopy/extensions/fxdriver#googlecode.com/components/driver-component.js:9089)
at WebLoadingListener/e (file:///tmp/tmp77bOby/webdriver-py-profilecopy/extensions/fxdriver#googlecode.com/components/driver-component.js:5145)
at WebLoadingListener/< (file:///tmp/tmp77bOby/webdriver-py-profilecopy/extensions/fxdriver#googlecode.com/components/driver-component.js:5153)
at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmp77bOby/webdriver-py-profilecopy/extensions/fxdriver#googlecode.com/components/driver-component.js:625)
What could be problem? I checked the disk space and there are disk space left.
A timeout error can have a laundry list of possible issues. Loading a page after a year of smooth operation narrows it down a little, but there are still many possibilities. Connection speeds sometimes change, sometimes the page you're loading up has added features that cause it to take longer to load or was just written poorly so it loads slowly... you get the idea. Without the code of the page or your code to look at, I can only suggest two fixes.
First, in the code of Selenium2Library, there is a timeout variable somewhere that can be set with Set Selenium Timeout. The default is 5 seconds, but if your page is taking longer to load, then increasing it might solve your problem. This assumes that your page loads at a reasonable rate in manual testing and that opening it is the least of your concerns.
Second, it's possible that you're testing an AngularJS application, not a normal website. If that's true, then you're going to want to use ExtendedSelenium2Library, not Selenium2Library. ExtendedSelenium2Library is better-equipped to deal with AngularJS applications and includes code to wait for Angular applications to load.
The old webdriver.xpi is buggy about page load handling. Timers are not correctly canceled, resulting in random windows switches and memory leaks. I copy here some replacement code that may be useful to anybody.
var WebLoadingListener = function(a, b, c, d) {
if ("none" == Utils.getPageLoadStrategy()) {
b(!1, !0);
} else {
this.logger = fxdriver.logging.getLogger("fxdriver.WebLoadingListener");
this.loadingListenerTimer = new fxdriver.Timer;
this.browser = a;
var self = this;
var e = function(a, c) {
self.destroy ();
b(a, c);
};
this.handler = buildHandler(a, e, d);
a.addProgressListener(this.handler);
-1 == c && (c = 18E5);
this.loadingListenerTimer.setTimeout(function() {
e(!0);
}, c);
WebLoadingListener.listeners [this.handler] = this;
goog.log.warning(this.logger, "WebLoadingListener created [" + Object.keys (WebLoadingListener.listeners).length + "] " + d.document.location);
}
};
WebLoadingListener.listeners = {};
WebLoadingListener.removeListener = function(a, b) {
if (b.constructor !== WebLoadingListener) {
b = WebLoadingListener.listeners [b];
}
b.destroy ();
};
WebLoadingListener.prototype.destroy = function() {
if (this.browser) {
this.loadingListenerTimer.cancel();
this.browser.removeProgressListener && this.handler && this.browser.removeProgressListener(this.handler);
delete WebLoadingListener.listeners [this.handler]
this.loadingListenerTimer = undefined;
this.browser = undefined;
goog.log.warning(this.logger, "WebLoadingListener destroyed [" + Object.keys (WebLoadingListener.listeners).length + "]");
}
};
enter code here

Difference Between Two Recursive Methods

I wanted to reflect a binary tree, such that all nodes on the left ended up on the right, and vice versa.
Something like :
A
/ \
B C
/ / \
D E F
would become
A
/ \
C B
/ \ \
F E D
I noticed that, while writing my solution, this code worked:
static Tree getReflection(Tree root) {
if(root == null) {
return null;
}
Tree reflect = root;
Tree subRight = getReflection(root.right);
Tree subLeft = getReflection(root.left);
reflect.left = subRight;
reflect.right = subLeft;
return reflect;
}
And yet, this one doesn't:
static Tree getReflection(Tree root) {
if(root == null) {
return null;
}
Tree reflect = root;
reflect.left = getReflection(root.right);
reflect.right = getReflection(root.left);
return reflect;
}
Can someone explain to me why? To me, they seem like identical methods, except one uses temporary tree variables.
Look at your first statement in each: when you assign
reflect = root
, the two variables now point to the same memory location. Now, let's look at the operation of the second routine:
Tree reflect = root;
// reflect and root now refer to exactly the same tree.
reflect.left = getReflection(root.right);
// reflect the right subtree; make that the new left subtree.
reflect.right = getReflection(root.left);
// Grab that new subtree, re-reflect it, and put it back on the right.
The original left subtree is lost, replaced by a reflection of the right.
In the first routine, you saved them in local variables until you'd done both reflections.
It is because in the second function (the one that doesn't work), you are assigning the reflected result to your left node and then using that as input to the reflection that you assign to your right node.
Tree reflect = root;
reflect.left = getReflection(root.right);
reflect.right = getReflection(root.left);

Resources