src/revwalk.c


Log

Author Commit Date CI Message
Edward Thomson f673e232 2018-12-27T13:47:34 git_error: use new names in internal APIs and usage Move to the `git_error` name in the internal API for error-related functions.
Edward Thomson 168fe39b 2018-11-28T14:26:57 object_type: use new enumeration names Use the new object_type enumeration names within the codebase.
Patrick Steinhardt e7873eb2 2018-11-29T08:00:31 Merge pull request #4888 from TheBB/add-cb revwalk: Allow changing hide_cb
Patrick Steinhardt 852bc9f4 2018-11-23T19:26:24 khash: remove intricate knowledge of khash types Instead of using the `khiter_t`, `git_strmap_iter` and `khint_t` types, simply use `size_t` instead. This decouples code from the khash stuff and makes it possible to move the khash includes into the implementation files.
Eivind Fonn 0836f069 2018-11-14T16:08:30 revwalk: Allow changing hide_cb Since git_revwalk objects are encouraged to be reused, a public interface for changing hide_cb is desirable.
Carlos Martín Nieto 12a1790d 2018-09-17T14:49:46 revwalk: only check the first commit in the list for an earlier timestamp This is not a big deal, but it does make us match git more closely by checking only the first. The lists are sorted already, so there should be no functional difference other than removing a possible check from every iteration in the loop.
Carlos Martín Nieto 46f35127 2018-09-17T14:39:58 revwalk: use the max value for a signed integer When porting, we overlooked that the difference between git's and our's time representation and copied their way of getting the max value. Unfortunately git was using unsigned integers, so `~0ll` does correspond to their max value, whereas for us it corresponds to `-1`. This means that we always consider the last date to be smaller than the current commit's and always think commits are interesting. Change the initial value to the macro that gives us the maximum value on each platform so we can accurately consider commits interesting or not.
Etienne Samson aa8cb586 2018-08-21T01:12:11 revwalk: The left operand of '<' is a garbage value At line 594, we do this : if (error < 0) return error; but if nothing was pushed in a GIT_SORT_TIME revwalk, we'd return uninitialized stack data.
Julian Ganz a4ffbae4 2018-07-29T11:46:05 revwalk: remove tautologic condition for hiding a commit The contition cannot be reached with `commit->uninteresting` being true: either a `break` or a `continue` statement will be hit in this case.
Nika Layzell 4fd81c53 2018-06-18T19:43:53 Clear revwalk sorting when resetting Currently we fail to clear the sorting flag for revwalks when resetting. This caused a poor interaction with the limited flag during a recent patch. This patch clears the revwalk sorting flag and causes it to no longer persist over resets.
Edward Thomson cc9c9522 2018-06-18T12:10:17 Merge pull request #4606 from libgit2/cmn/revwalk-iteration revwalk: avoid walking the entire history when output is unsorted
Edward Thomson ff98fec0 2018-06-18T10:25:07 revwalk: formatting updates
Patrick Steinhardt ecf4f33a 2018-02-08T11:14:48 Convert usage of `git_buf_free` to new `git_buf_dispose`
Patrick Steinhardt 54fd80e3 2018-04-12T13:32:27 revwalk: fix uninteresting revs sometimes not limiting graphwalk When we want to limit our graphwalk, we use the heuristic of checking whether the newest limiting (uninteresting) revision is newer than the oldest interesting revision. We do so by inspecting whether the first item's commit time of the user-supplied list of revisions is newer than the last added interesting revision. This is wrong though, as the user supplied list is in no way guaranteed to be sorted by increasing commit dates. This could lead us to abort the revwalk early before applying all relevant limiting revisions, outputting revisions which should in fact have been hidden. Fix the heuristic by instead checking whether _any_ of the limiting commits was made earlier than the last interesting commit. Add a test.
Carlos Martín Nieto ef682410 2018-04-11T17:52:51 revwalk: remove one useless layer of functions We don't currently need to have anything that's different between `get_revision` and `get_one_revision` so let's just remove the inner function and make the code more straightforward.
Carlos Martín Nieto 2a6d0956 2018-04-01T14:01:52 revwalk: avoid walking the entire history when output is unsorted As part of reducing our divergence from git, its code for revwalk was ported into our codebase. A detail about when to limit the list was lost and we ended up always calling that code. Limiting the list means performing the walk and creating the final list of commits to be output during the preparation stage. This is unavoidable when sorting and when there are negative refs. We did this even when asked for unsorted output with no negative refs, which you might do to retrieve something like the "last 10 commits on HEAD" for a nominally unsorted meaning of "last". This commit adds and sets a flag indicating when we do need to limit the list, letting us avoid doing so when we can. The previously mentioned query thus no longer loads the entire history of the project during the prepare stage, but loads it iteratively during the walk.
Patrick Steinhardt 0c7f49dd 2017-06-30T13:39:01 Make sure to always include "common.h" first Next to including several files, our "common.h" header also declares various macros which are then used throughout the project. As such, we have to make sure to always include this file first in all implementation files. Otherwise, we might encounter problems or even silent behavioural differences due to macros or defines not being defined as they should be. So in fact, our header and implementation files should make sure to always include "common.h" first. This commit does so by establishing a common include pattern. Header files inside of "src" will now always include "common.h" as its first other file, separated by a newline from all the other includes to make it stand out as special. There are two cases for the implementation files. If they do have a matching header file, they will always include this one first, leading to "common.h" being transitively included as first file. If they do not have a matching header file, they instead include "common.h" as first file themselves. This fixes the outlined problems and will become our standard practice for header and source files inside of the "src/" from now on.
Adam Niedzielski c11c08a5 2017-03-09T14:01:10 Skip uninteresting commits in revwalk timesort iterator Fixes #4099
Patrick Steinhardt 0d716905 2017-01-27T15:23:15 oidmap: remove GIT__USE_OIDMAP macro
Patrick Steinhardt 85d2748c 2017-01-27T14:05:10 khash: avoid using `kh_key`/`kh_val` as lvalue
Patrick Steinhardt f31cb45a 2017-01-25T15:31:12 khash: avoid using `kh_put` directly
Patrick Steinhardt cb18386f 2017-01-25T14:26:58 khash: avoid using `kh_val`/`kh_value` directly
Patrick Steinhardt a853c527 2017-01-25T14:14:32 khash: avoid using `kh_get` directly
Patrick Steinhardt 64e46dc3 2017-01-25T14:14:12 khash: avoid using `kh_end` directly
Patrick Steinhardt 9694d9ba 2017-01-25T14:09:17 khash: avoid using `kh_foreach`/`kh_foreach_value` directly
Edward Thomson 909d5494 2016-12-29T12:25:15 giterr_set: consistent error messages Error messages should be sentence fragments, and therefore: 1. Should not begin with a capital letter, 2. Should not conclude with punctuation, and 3. Should not end a sentence and begin a new one
Patrick Steinhardt 013ecb4f 2016-11-25T15:00:50 revwalk: do not re-declare `commit` variable
Carlos Martín Nieto fedc05c8 2016-10-06T18:13:34 revwalk: don't show commits that become uninteresting after being enqueued When we read from the list which `limit_list()` gives us, we need to check that the commit is still interesting, as it might have become uninteresting after it was added to the list.
Carlos Martín Nieto 82d4c0e6 2016-10-05T12:55:53 revwalk: update the description for the default sorting It changed from implementation-defined to git's default sorting, as there are systems (e.g. rebase) which depend on this order. Also specify more explicitly how you can get git's "date-order".
Carlos Martín Nieto ea1ceb7f 2016-10-05T12:23:26 revwalk: remove a useless enqueueing phase for topological and default sorting After `limit_list()` we already have the list in time-sorted order, which is what we want in the "default" case. Enqueueing into the "unsorted" list would just reverse it, and the topological sort will do its own sorting if it needs to.
Carlos Martín Nieto 9db367bf 2016-09-27T16:14:42 revwalk: get rid of obsolete marking code We've now moved to code that's closer to git and produces the output during the preparation phase, so we no longer process the commits as part of generating the output. This makes a chunk of code redundant, as we're simply short-circuiting it by detecting we've processed the commits alrady.
Carlos Martín Nieto e93b7e32 2016-09-27T13:35:48 revwalk: style change Change the condition for returning 0 more in line with that we write elsewhere in the library.
Carlos Martín Nieto 48c64362 2016-09-27T11:59:24 revwalk: port over the topological sorting After porting over the commit hiding and selection we were still left with mistmaching output due to the topologial sort. This ports the topological sorting code to make us match with our equivalent of `--date-order` and `--topo-order` against the output from `rev-list`.
Carlos Martín Nieto 6708618c 2016-07-21T01:24:12 revwalk: get closer to git We had some home-grown logic to figure out which objects to show during the revision walk, but it was rather inefficient, looking over the same list multiple times to figure out when we had run out of interesting commits. We now use the lists in a smarter way. We also introduce the slop mechanism to determine when to stpo looking. When we run out of interesting objects, we continue preparing the walk for another 5 rounds in order to make it less likely that we miss objects in situations with complex graphs.
Patrick Steinhardt c5bd70d1 2016-02-23T11:48:30 revwalk: use GITERR_CHECK_ALLOC_BUF
Vicent Marti 1e5e02b4 2015-10-27T17:26:04 pool: Simplify implementation
Stefan Widgren c369b379 2015-07-31T16:23:11 Remove extra semicolon outside of a function Without this change, compiling with gcc and pedantic generates warning: ISO C does not allow extra ‘;’ outside of a function.
Edward Thomson c332bb70 2015-04-16T19:26:40 Merge pull request #3042 from libgit2/cmn/odd-slowdown revwalk: detect when we're out of interesting commits
Carlos Martín Nieto a0541695 2015-04-14T03:26:45 revwalk: detect when we're out of interesting commits When walking backwards and marking parents uninteresting, make sure we detect when the list of commits we have left has run out of uninteresting commits so we can stop marking commits as uninteresting. Failing to do so can mean that we walk the whole history marking everything uninteresting, which eats up time, CPU and IO for with useless work. While pre-marking does look for this, we still need to check during the main traversal as there are setups for which pre-marking does not leave enough information in the commits. This can happen if we push a commit and hide its parent.
Carlos Martín Nieto 50fdfe2b 2015-04-08T23:51:49 revwalk: don't insert uninteresting commits into the queue When a commit is first set as unintersting and then pushed, we must take care that we do not put it into the commit list as that makes us return at least that commit (but maybe more) as we've inserted it into the list because we have the assumption that we want anything in the commit list.
Carlos Martín Nieto b63b76e0 2014-10-12T11:42:31 Reorder some khash declarations Keep the definitions in the headers, while putting the declarations in the C files. Putting the function definitions in headers causes them to be duplicated if you include two headers with them.
Edward Thomson 392702ee 2015-02-09T23:41:13 allocations: test for overflow of requested size Introduce some helper macros to test integer overflow from arithmetic and set error message appropriately.
Carlos Martín Nieto 753e17b0 2014-11-19T18:42:29 peel: reject bad queries with EINVALIDSPEC There are some combination of objects and target types which we know cannot be fulfilled. Return EINVALIDSPEC for those to signify that there is a mismatch in the user-provided data and what the object model is capable of satisfying. If we start at a tag and in the course of peeling find out that we cannot reach a particular type, we return EPEEL.
Carlos Martín Nieto d6afda62 2014-10-08T17:17:31 revwalk: clear first-parent flag on reset This should have been included when implementing the feature but was missed.
Carlos Martín Nieto 9b5d6cea 2014-10-08T17:14:48 revwalk: catch no-push and no-hide cases If there have been no pushes, we can immediately return ITEROVER. If there have been no hides, we must not run the uninteresting pre-mark phase, as we do not want to hide anything and this would simply cause us to spend time loading objects.
Carlos Martín Nieto e7970576 2014-10-08T15:52:11 revwalk: mark uninteresting only up to the common ancestors This introduces a phase at the start of preparing a walk which pre-marks uninteresting commits, but only up to the common ancestors. We do this in a similar way to git, by walking down the history and marking (which is what we used to do), but we keep a time-sorted priority queue of commits and stop marking as soon as there are only uninteresting commits in this queue. This is a similar rule to the one used to find the merge-base. As we keep inserting commits regardless of the uninteresting bit, if there are only uninteresting commits in the queue, it means we've run out of interesting commits in our walk, so we can stop. The old mark_unintesting() logic is still in place, but that stops walking if it finds an already-uninteresting commit, so it will stop on the ones we've pre-marked; but keeping it allows us to also hide those that are hidden via the callback.
Carlos Martín Nieto ad66bf88 2014-10-08T10:45:47 revwalk: keep a single list of user inputs The old separation was due to the old merge-base finding, so it's no longer necessary.
Carlos Martín Nieto 42835aa6 2014-10-08T10:24:06 revwalk: clear the flags on reset These store merge-base information which is only valid for a single run.
Carlos Martín Nieto 9746b36c 2014-07-24T16:46:59 revwalk: remove preallocation of the uninteresting commits Preallocating two commits doesn't make much sense as leaving allocation to the first array usage will allocate a sensible size with room for growth. This preallocation has also been hiding issues with strict aliasing in the tests, as we have fairly simple histories and never trigger the growth.
Carlos Martín Nieto f9a97667 2014-06-11T00:06:44 revwalk: more sensible array handling Instead of using a sentinel empty value to detect the last commit, let's check for when we get a NULL from popping the stack, which lets us know when we're done. The current code causes us to read uninitialized data, although only on RHEL/CentOS 6 in release mode. This is a readability win overall.
Anurag Gupta 3bc3d797 2014-03-31T15:15:32 No need to find merge base.
Anurag Gupta 7ca1584b 2014-03-11T11:49:19 Conforming to libgit2 coding style.
Anurag Gupta 46e4d82d 2014-03-10T16:21:56 Remove unused push_cb_data
Anurag Gupta 892aa808 2014-03-10T12:00:33 Callback to hide commits in revision walker.
Carlos Martín Nieto 704b55cc 2014-03-20T20:24:11 revwalk: don't try to find merge bases when there can be none As a way to speed up the cases where we need to hide some commits, we find out what the merge bases are so we know to stop marking commits as uninteresting and avoid walking down a potentially very large amount of commits which we will never see. There are however two oversights in current code. The merge-base finding algorithm fails to recognize that if it is only given one commit, there can be no merge base. It instead walks down the whole ancestor chain needlessly. Make it return an empty list immediately in this situation. The revwalk does not know whether the user has asked to hide any commits at all. In situation where the user pushes multiple commits but doesn't hide any, the above fix wouldn't do the trick. Keep track of whether the user wants to hide any commits and only run the merge-base finding algorithm when it's needed.
Vicent Marti c4ee3b54 2014-02-07T18:32:06 Merge pull request #2100 from libgit2/rb/update-pqueue Replace priority queue code with implementation from hashsig
Carlos Martín Nieto af817202 2014-02-01T15:29:16 revwalk: remove usage of foreach
Carlos Martín Nieto d465e4e9 2014-02-01T15:19:13 revwalk: ignore wrong object type in glob pushes Pushing a whole namespace can cause us to attempt to push non-committish objects. Catch this situation and special-case it for ignoring this.
Carlos Martín Nieto f61272e0 2014-02-01T12:51:36 revwalk: accept committish objects Let the user push committish objects and peel them to figure out which commit to push to our queue. This is for convenience and for allowing uses of git_revwalk_push_glob(w, "tags") with annotated tags.
Russell Belfer 882c7742 2014-02-04T10:01:37 Convert pqueue to just be a git_vector This updates the git_pqueue to simply be a set of specialized init/insert/pop functions on a git_vector. To preserve the pqueue feature of having a fixed size heap, I converted the "sorted" field in git_vectors to a more general "flags" field so that pqueue could mix in it's own flag. This had a bunch of ramifications because a number of places were directly looking at the vector "sorted" field - I added a couple new git_vector helpers (is_sorted, set_sorted) so the specific representation of this information could be abstracted.
Russell Belfer 4075e060 2014-02-03T21:02:08 Replace pqueue with code from hashsig heap I accidentally wrote a separate priority queue implementation when I was working on file rename detection as part of the file hash signature calculation code. To simplify licensing terms, I just adapted that to a general purpose priority queue and replace the old priority queue implementation that was borrowed from elsewhere. This also removes parts of the COPYING document that no longer apply to libgit2.
Russell Belfer 25e0b157 2013-12-06T15:07:57 Remove converting user error to GIT_EUSER This changes the behavior of callbacks so that the callback error code is not converted into GIT_EUSER and instead we propagate the return value through to the caller. Instead of using the giterr_capture and giterr_restore functions, we now rely on all functions to pass back the return value from a callback. To avoid having a return value with no error message, the user can call the public giterr_set_str or some such function to set an error message. There is a new helper 'giterr_set_callback' that functions can invoke after making a callback which ensures that some error message was set in case the callback did not set one. In places where the sign of the callback return value is meaningful (e.g. positive to skip, negative to abort), only the negative values are returned back to the caller, obviously, since the other values allow for continuing the loop. The hardest parts of this were in the checkout code where positive return values were overloaded as meaningful values for checkout. I fixed this by adding an output parameter to many of the internal checkout functions and removing the overload. This added some code, but it is probably a better implementation. There is some funkiness in the network code where user provided callbacks could be returning a positive or a negative value and we want to rely on that to cancel the loop. There are still a couple places where an user error might get turned into GIT_EUSER there, I think, though none exercised by the tests.
Russell Belfer dab89f9b 2013-12-04T21:22:57 Further EUSER and error propagation fixes This continues auditing all the places where GIT_EUSER is being returned and making sure to clear any existing error using the new giterr_user_cancel helper. As a result, places that relied on intercepting GIT_EUSER but having the old error preserved also needed to be cleaned up to correctly stash and then retrieve the actual error. Additionally, as I encountered places where error codes were not being propagated correctly, I tried to fix them up. A number of those fixes are included in the this commit as well.
Russell Belfer 106c12f1 2013-09-23T13:31:15 Remove regex usage from places that don't need it In revwalk, we are doing a very simple check to see if a string contains wildcard characters, so a full regular expression match is not needed. In remote listing, now that we have git_config_foreach_match with full regular expression matching, we can take advantage of that and eliminate the regex here, replacing it with much simpler string manipulation.
Carlos Martín Nieto 15f7b9b8 2013-09-08T00:52:26 revwalk: allow simplifying by first-parent When enabled, only the first parent of each commit will be queued, enabling a simple way of using first-parent simplification.
Carlos Martín Nieto fb23d05f 2013-08-17T07:58:55 revwalk: make mark_unintersting use a loop Using a recursive function can blow the stack when dealing with long histories. Use a loop instead to limit the call chain depth. This fixes #1223.
Carlos Martín Nieto 2b562c3a 2013-05-04T16:32:58 refs: remove the OID/SYMBOLIC filtering Nobody should ever be using anything other than ALL at this level, so remove the option altogether. As part of this, git_reference_foreach_glob is now implemented in the frontend using an iterator. Backends will later regain the ability of doing the glob filtering in the backend.
Vicent Marti cbda09d0 2013-04-15T23:40:46 git_revision -> git_revspec
Vicent Marti 36c2dfed 2013-04-15T23:32:40 Is this crazy?
Ben Straub 299a224b 2013-04-15T12:00:04 Change git_revparse to output git_object pointers This will probably prevent many lookup/free operations in calling code.
Ben Straub 1aa21fe3 2013-04-09T05:03:51 Deprecate git_revparse_single and _rangelike
Greg Price af079d8b 2013-03-03T20:54:23 revwalk: Parse revision ranges All the hard work is already in revparse. Signed-off-by: Greg Price <price@mit.edu>
Edward Thomson 359fc2d2 2013-01-08T17:07:25 update copyrights
Russell Belfer d5e44d84 2012-11-29T17:02:27 Fix function name and add real error check `revwalk.h:commit_lookup()` -> `git_revwalk__commit_lookup()` and make `git_commit_list_parse()` do real error checking that the item in the list is an actual commit object. Also fixed an apparent typo in a test name.
Ben Straub 4ff192d3 2012-11-26T19:47:47 Move merge functions to merge.c In so doing, promote commit_list to git_commit_list, with its own internal API header.
Ben Straub 2508cc66 2012-11-18T21:38:08 Rename ref and reflog apis for consistency
Michael Schubert 8060cdc9 2012-09-27T14:59:43 revwalk: fix off-by-one error Fixes #921.
Sascha Cunz 857323d4 2012-09-09T15:53:57 git_mergebase: Constness-Fix for consistency
Russell Belfer f335ecd6 2012-08-30T14:24:16 Diff iterators This refactors the diff output code so that an iterator object can be used to traverse and generate the diffs, instead of just the `foreach()` style with callbacks. The code has been rearranged so that the two styles can still share most functions. This also replaces `GIT_REVWALKOVER` with `GIT_ITEROVER` and uses that as a common error code for marking the end of iteration when using a iterator style of object.
Michael Schubert 4e323ef0 2012-08-27T10:51:01 revwalk: refuse push of non-commit objects Check the type of the pushed object immediately instead of starting the walk and failing in between.
nulltoken 118cf57d 2012-07-04T16:06:07 revwalk: relax the parsing of the commit time
nulltoken 11634346 2012-06-22T17:04:16 revwalk: make git_revwalk_(push|hide)_glob() leverage git_reference_foreach_glob()
Vicent Martí 31eed56b 2012-06-18T17:36:14 Merge pull request #753 from nulltoken/topic/merge-base-many Expose git_merge_base_many()
Russell Belfer 471fa05e 2012-06-11T15:38:33 Fix fragile commit parsing in revwalk
nulltoken b46bdb22 2012-05-25T16:28:53 merge: Expose git_merge_base_many()
Vicent Martí 904b67e6 2012-05-18T01:48:50 errors: Rename error codes
Vicent Martí e172cf08 2012-05-18T01:21:06 errors: Rename the generic return codes
Nico von Geyso 0b86fdf9 2012-05-15T17:03:07 really reset walker with git_revwalk_reset From the description of git_revwalk_reset in revwalk.h the function should clear all pushed and hidden commits, and leave the walker in a blank state (just like at creation). Apparently everything gets reseted appart of pushed commits (walk->one and walk->twos) This fix should reset the walker properly.
Vicent Martí 3fbcac89 2012-05-02T19:56:38 Remove old and unused error codes
Russell Belfer 821f6bc7 2012-04-26T13:04:54 Fix Win32 warnings
Russell Belfer 3fc5c65d 2012-04-25T15:24:05 Merge pull request #642 from arrbee/mem-pools Memory pools and khash hashtables
Russell Belfer c2b67043 2012-04-25T15:20:28 Rename git_khash_str to git_strmap, etc. This renamed `git_khash_str` to `git_strmap`, `git_hash_oid` to `git_oidmap`, and deletes `git_hashtable` from the tree, plus adds unit tests for `git_strmap`.
Russell Belfer 01fed0a8 2012-04-25T10:36:01 Convert hashtable usage over to khash This updates khash.h with some extra features (like error checking on allocations, ability to use wrapped malloc, foreach calls, etc), creates two high-level wrappers around khash: `git_khash_str` and `git_khash_oid` for string-to-void-ptr and oid-to-void-ptr tables, then converts all of the old usage of `git_hashtable` over to use these new hashtables. For `git_khash_str`, I've tried to create a set of macros that yield an API not too unlike the old `git_hashtable` API. Since the oid hashtable is only used in one file, I haven't bother to set up all those macros and just use the khash APIs directly for now.
Russell Belfer da3b391c 2012-04-18T10:57:08 Convert revwalk to use git_pool This removes the custom paged allocator from revwalk and replaces it with a `git_pool`.
Carlos Martín Nieto 2e3a0055 2012-04-16T11:58:46 revwalk: return GIT_EREVWALKER earlier if no references were pushed In the case that walk->one is NULL, we know that we have no positive references, so we already know that the revwalk is over.
Russell Belfer 26515e73 2012-04-23T10:06:31 Rename to git_reference_name_to_oid
Russell Belfer 44ef8b1b 2012-04-13T13:00:10 Fix warnings on 64-bit windows builds This fixes all the warnings on win64 except those in deps, which come from the regex code.
Russell Belfer f201d613 2012-04-13T10:33:14 Add git_reference_lookup_oid and lookup_resolved Adds a new public reference function `git_reference_lookup_oid` that directly resolved a reference name to an OID without returning the intermediate `git_reference` object (hence, no free needed). Internally, this adds a `git_reference_lookup_resolved` function that combines looking up and resolving a reference. This allows us to be more efficient with memory reallocation. The existing `git_reference_lookup` and `git_reference_resolve` are reimplmented on top of the new utility and a few places in the code are changed to use one of the two new functions.
Carlos Martín Nieto eb8117b8 2012-04-12T20:25:07 error-handling: revwalk
Carlos Martín Nieto f9e4bfa3 2012-03-04T03:00:35 revwalk: use a priority queue for calculating merge bases As parents are older than their children, we're appending to the commit list most of the time, which makes an ordered linked list quite inefficient. While we're there, don't sort the results list in the main loop, as we're sorting them afterwards and it creates extra work.