-
Notifications
You must be signed in to change notification settings - Fork 504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow patchs in diff format #83
Conversation
The |
Maybe, I'm not sure. I've looked for some info about that argument and seems to be related to CVS revisions, that make sense. According to this text, there could appear zero, one or more times, so maybe I should change the RegExp to show this case... Other option is to ignore all the flags and get only the last fragment (the index path), what do you think? |
Lets ignore everything but the path component. Can you add a test case to cover this? |
let hunk = hunks[i]; | ||
|
||
if (!hunkFits(hunk, hunk.oldStart - 1)) { | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What behavior does this change that is necessary to do two iterations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is WiP to allow to calculate the location offset where the hunks best fit. This is to fix issue #84
I have reading some docs and thinking about this thing, and I believe we are taking a bad approach. We are considering it like the |
It's said, what I means is that according to docs both the |
Ok, offsets now are correctly calculated and NodeOS can be able to download all its build dependencies purely on Javascript :-) I'mgoing to write some tests to prevent regressions. |
Test for hunk offsets added. |
minLine = 0, | ||
toPos = offset + hunk.oldStart - 1; | ||
|
||
for (;;) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is really hard to follow and I worry that it's going to lead to confusion down the road. Rather than having side effects that terminate the loop in the middle of the block and the loop written as an infinite loop, I think it would be clearer to have the termination case expressed in the for
/while
statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an optimization, the alternative is to have the old code and use a conditional to check it, or do the check twice on the most common case (the hunk fits at the first try, when localOffset
is zero). This has only moved the block to check the current or next line before the loop, so it's checked always in a loop rollback fashion. The same would be achieved by doing the check previously to enter the loop, but code is duplicated. I can add more comments if you don't see it clear.
I've improved the code documentation. |
localOffset = 0, | ||
toPos = offset + hunk.oldStart - 1; | ||
|
||
for (;;) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After coming back to this a few days later, I'm still worried that I'm not going to be able to maintain this.
What if instead we extract out the iteration logic into an iterator? Something like:
function distanceIterator(target, minimum, maximum) {
let wantForward = true,
backwardExhausted = false,
forwardExhausted = false,
offset = 0;
return function iterate() {
// Continue iteration on the rear when the
if (forwardExhausted) {
wantForward = false;
offset++;
}
if (!wantForward) {
// Check if we have a potential position behind us
let candidate = target - offset;
if (candidate > minimum) {
wantForward = true;
return candidate;
} else {
backwardExhausted = true;
}
}
// Check if we have a potential position in front of us
candidate = target + offset;
if (candidate < maximium) {
wantForward = false;
offset++;
return candidate;
} else if (!backwardExhausted) {
// We've exhausted the forward section, reenter to continue
// iteration on the behind.
forwardExhausted = true;
return iterate();
}
};
}
Which can live in it's own file and we can unit test in isolation. This loop here then becomes something like:
for (let i = 0; i < hunks.length; i++) {
let ...
toPos = offest + hunk.oldStart + 1,
maxLine = lines.length - hunk.oldLines,
iterator = distanceIterator(toPos, minLine, maxLine),
toCheck = iterator();
while (toCheck !== null) {
if (hunkFits(hunk, toCheck)) {
hunk.offset = toCheck;
break;
}
toCheck = iterator();
}
}
(I have not actually tested or even run this code, so it might need some work to get it running)
I think separating general flip flopping iteration and checking the hunk itself into separate code will help with clarity as well as give us a nice reusable component for this iteration should we need it in other locations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think separating general flip flopping iteration and checking the hunk itself into separate code will help with clarity as well as give us a nice reusable component for this iteration should we need it in other locations.
I find this code a little bit more complicated and less eficient, but I like the idea of separate the flip-flop logic from the main loop. I'll fetch your code and try to check it out :-)
I've just splitted the logic to calculate candidates on an iterator. Maybe the code gets more readable, but I think it's more complicated and less performance, but at least it does the job. |
|
||
let iterator = distanceIterator(toPos, minLine, maxLine); | ||
|
||
for (; localOffset != undefined; localOffset = iterator()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need !==
here or != null
otherwise zero will fail. We should have a test case for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need !== here or != null otherwise zero will fail.
[piranna@Mabuk:~/Proyectos/NodeOS/node_modules]
(vagga) > node
> 0 != undefined
true
>
I think it's not needed... :-) But I could agree on the !== undefined
, in any case is the only thing it will return... I left it this way to be more generic.
We should have a test case for that.
A test case for what, exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it's been too long that I've been using != null
. Generally prefer != null
for "anything other than null and undefined" and "!== undefined" for "just looking for undefined". (I actually thought that was in the linter rules, but I guess not).
Little bit of a nit picky change but would be nice to have so it doesn't cause confusion down the road.
Test case: To make sure that it can patch at an offset of zero.
return true; | ||
} | ||
|
||
function distanceIterator(toPos, minLine, maxLine) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a separate module to help make things clearer.
Thanks for making the changes. Regarding complicated, by breaking out the components, it should be easier to think about and diagnose what is going. Not always the case, but I've been burned by a few patches in this repo that I didn't fully understand that caused me great headaches down the road. Regarding performance this is still the same O, something like |
Sometimes overengineering promotes this (at least in my case), so I try to keep things as simple and minimal as possible, so it's also less error-prone.
It's the same O, but implementation is more verbose so it will be slower, that's what I said about performance. |
@@ -60,6 +60,5 @@ | |||
"semver": "^5.0.3", | |||
"webpack": "^1.12.2", | |||
"webpack-dev-server": "^1.12.0" | |||
}, | |||
"optionalDependencies": {} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep the changes focused on this PR.
Done.
That's the trivial case, when offset is zero it fitted at first try, so it didn't need to exec the |
I was able to put So, to summarize, what changes need to be done (if any) so this pull-request can land on upstream? I need this to be available as soon as possible for so NodeOS (my bachelor thesis) can work... :-/ |
Merging this now and I'll take care of the rest of the cleanup. |
This was merged, but the combination of rebase and master on master merge from the CLI commands caused github to not detect this. Closing this out, but it is merged. |
048e7f7 is what I was intending. Doing this and explicit functionality tests in the micro scale helps dramatically with code quality. Best of luck with your bachelors. |
Yes, this happened to me before. Sometimes it detect it, though. Don't worry :-)
Ok, I see. I'm not too much to split such code to independent files (I prefer to have it near to where it's used, or at least as global private function to reduce memory usage) except if it has a clear own entity (so maybe I would put it on its own module) or if it's being used from several places. I like the description that you put there, simple and clear. I didn't think about it, but would be a good candidate for a simple test :-)
Thank you! :-) You can see how it goes on at https://github.com/NodeOS/NodeOS :-) |
This fixes issue #82