Marko, have you had a chance to look at this PR? Do these use cases make sense? Any idea why they are failing? Should we reopen #619 as a reminder to keep looking at this PR? It would be nice to settle this for GA.
On Sat, Jun 20, 2015 at 9:27 AM, Matt Frantz <[email protected]> wrote: > Since this was really about creating regressions for TINKERPOP3-619, I > created a PR with those regressions. > > https://github.com/apache/incubator-tinkerpop/pull/86 > > As stated in the PR, a few of these cases now fail, so take a look and let > me know if I can help. > > On Fri, Jun 19, 2015 at 7:34 PM, Marko Rodriguez <[email protected]> > wrote: > >> Hey Matt, >> >> Can you make a "formal" ticket about the problem you are seeing, please? >> >> Thanks, >> Marko. >> >> http://markorodriguez.com >> >> On Jun 19, 2015, at 7:09 PM, Matt Frantz <[email protected]> >> wrote: >> >> > Cool. Can't wait to get my hands on GA! >> > >> > I just read through SelectStep/SelectOneStep (again), and I'm pretty >> sure >> > that if you do a select of a nonexistent label, it will stop the >> traversal >> > rather than raise "step with provided label does not exist" exception, >> like >> > in olden times. That is because Scoping.getOptionalScopeValueByKey >> checks >> > Path.hasLabel. That makes the Path.get exception case unreachable from >> > select, which is what we want. Not sure what to do about that, if >> > anything, but I am unsure about regression test coverage. This >> requirement >> > came from TINKERPOP3-619 (select should not throw). >> > >> > g.V().select('a') [should produce nothing] >> > g.V().valueMap().select('a') [should produce nothing] >> > >> > >> > On Fri, Jun 19, 2015 at 12:24 PM, Marko Rodriguez <[email protected] >> > >> > wrote: >> > >> >> Hi Matt, >> >> >> >> Okay, we now have: >> >> >> >> Pop.first >> >> Pop.last >> >> Pop.all >> >> >> >> And there are two "get" methods: >> >> >> >> A get(label) // could be a singleton, list, or exception >> >> A get(pop,label) // single (or exception if doesn't exist) or >> list >> >> (empty list if does not exist) >> >> >> >> Everything looks the same except: >> >> >> >> path.<List>get(Pop.all, "a").size() >> >> >> >> Good stuff man. Appreciate your patience on the matter --- that was >> like a >> >> 2 month ticket. >> >> >> >> Marko. >> >> >> >> http://markorodriguez.com >> >> >> >> On Jun 16, 2015, at 1:53 PM, Matt Frantz <[email protected]> >> >> wrote: >> >> >> >>> In contrast to the current "Path.get" (which aligns with the current >> >>> "select"), specifying Pop.all would ensure that you get a List even if >> >>> there is only one element. Thus, one could choose between the >> >> "containers >> >>> only when necessary" API and the "predictable type" API. >> >>> >> >>> For context, my application contains loops (repeat-until) that contain >> >>> labeled steps. Ahead of time, you don't know how many iterations you >> >> will >> >>> get. Thus, with the current "select" behavior, you don't know whether >> you >> >>> will get a single element (one iteration) or a List (more than one >> >>> iteration), so there has to be a check and a conversion into List. I >> >> would >> >>> almost always prefer a predictable type, so I would use Pop.all when I >> >> want >> >>> a List. (Of course, I sometimes want Pop.last, but that problem is >> now >> >>> solved.) >> >>> >> >>> If you change Path.get(label) to call Path.get(Pop.all, label), then >> >> select >> >>> would have to be modified, provided you want to preserve the >> "containers >> >>> only when necessary" API. >> >>> >> >>> On Tue, Jun 16, 2015 at 5:13 AM, Marko Rodriguez < >> [email protected]> >> >>> wrote: >> >>> >> >>>> Hi Matt, >> >>>> >> >>>> So I did Pop.first ("return collection[0]") and Pop.last (i.e. >> "return >> >>>> collection[collection.size() - 1]"). Pushed. >> >>>> >> >>>> Next, so by Pop.all you mean "return collection" ? Can you explain >> the >> >>>> context in which this enum would be used? Are you assuming that >> >>>> Path.getSingle() goes away and we have Path.get(Pop, label) with >> >>>> Path.get(label) defaulting to Pop.all? >> >>>> >> >>>> Thanks for your help with this, >> >>>> Marko. >> >>>> >> >>>> http://markorodriguez.com >> >>>> >> >>>> On Jun 15, 2015, at 10:56 AM, Matt Frantz < >> [email protected]> >> >>>> wrote: >> >>>> >> >>>>> How about a third choice that always returns a List? Pop.all? This >> >>>> would >> >>>>> provide the Java Generic type safety that fills our hearts with >> light. >> >>>>> >> >>>>> On Mon, Jun 15, 2015 at 9:49 AM, Matt Frantz < >> >> [email protected] >> >>>>> >> >>>>> wrote: >> >>>>> >> >>>>>> That works for me. >> >>>>>> >> >>>>>> On Mon, Jun 15, 2015 at 8:55 AM, Marko Rodriguez < >> >> [email protected]> >> >>>>>> wrote: >> >>>>>> >> >>>>>>> Ah. The plot thickens. >> >>>>>>> >> >>>>>>> I prefer to keep limit() and tail(). >> >>>>>>> >> >>>>>>> What if we do: >> >>>>>>> >> >>>>>>> Pop.first (was Pop.tail) >> >>>>>>> Pop.last (was Pop.head) >> >>>>>>> >> >>>>>>> Is then everything else consistent? >> >>>>>>> >> >>>>>>> Marko. >> >>>>>>> >> >>>>>>> http://markorodriguez.com >> >>>>>>> >> >>>>>>> On Jun 15, 2015, at 9:15 AM, Matt Frantz < >> [email protected] >> >>> >> >>>>>>> wrote: >> >>>>>>> >> >>>>>>>> In addition to unfold().tail(), there is tail(local), which is >> >>>>>>> consistent >> >>>>>>>> with unfold().tail() in that it grabs the "end" of the List (or >> >> Map). >> >>>>>>>> >> >>>>>>>> By "consistent throughout", I guess you mean "select's use of >> >>>> head/tail >> >>>>>>>> terminology should be consistent with established terminology in >> >> graph >> >>>>>>>> theory." You also say that List.iterator() emits values >> >> left-to-right >> >>>>>>>> (tail to head). However, the terminology that I am accustomed >> to is >> >>>>>>>> described on the wiki for a Linked list: "The 'head' of a list is >> >> its >> >>>>>>> first >> >>>>>>>> node. The 'tail' of a list may refer either to the rest of the >> list >> >>>>>>> after >> >>>>>>>> the head, or to the last node in the list." >> >>>>>>>> >> >>>>>>>> This terminology resonates in a cursory search ("stream head >> tail") >> >> to >> >>>>>>>> describe streams, i.e. "head" means the first thing that comes >> out >> >> of >> >>>> a >> >>>>>>>> stream, while "tail" means "everything except the head." With an >> >>>>>>> integer >> >>>>>>>> argument, "head(n)" resembles Gremlin's "limit(n)", if you think >> of >> >> a >> >>>>>>>> Gremlin traversal as a stream that produces traversers. >> >>>>>>>> >> >>>>>>>> The use of "head" and "tail" as Unix utilities is currently >> >> consistent >> >>>>>>> with >> >>>>>>>> the tail step's usage, in that they refer, respectively, to the >> >> first >> >>>>>>> and >> >>>>>>>> last objects in the stream. >> >>>>>>>> >> >>>>>>>> I feel that the two uses of "tail" should be consistent with each >> >>>> other >> >>>>>>>> within Gremlin, but I can see that they are currently drawn from >> >>>>>>> different >> >>>>>>>> disciplines of computer science. My preference would be to >> replace >> >>>>>>>> "limit/tail" with "first/last" to avoid such ambiguity. Then, we >> >> can >> >>>>>>> swap >> >>>>>>>> Pop head/tail as it was in the beginning. >> >>>>>>>> >> >>>>>>>> The idea of making "limit" and "tail" more obviously symmetric >> >> belies >> >>>>>>> the >> >>>>>>>> origin of "limit" as a terminology ported from RDBMS (I >> presume). I >> >>>> am >> >>>>>>> not >> >>>>>>>> opposed to synonyms/aliases, although the Gremlin language may be >> >> rich >> >>>>>>>> enough without them. >> >>>>>>>> >> >>>>>>>> I'd be happy to help with whatever solution is agreeable to the >> >>>>>>> community. >> >>>>>>>> I'll have some TP3 budget in a couple of days. >> >>>>>>>> >> >>>>>>>> My two cents. >> >>>>>>>> >> >>>>>>>> On Mon, Jun 15, 2015 at 6:55 AM, Marko Rodriguez < >> >>>> [email protected]> >> >>>>>>>> wrote: >> >>>>>>>> >> >>>>>>>>> Hi, >> >>>>>>>>> >> >>>>>>>>> So the way the select() puts things into a List (i.e. >> Path.get()), >> >>>>>>>>> currently, is good: >> >>>>>>>>> >> >>>>>>>>> gremlin> g.V().as('a').out('created').as('a').select('a') >> >>>>>>>>> ==>[v[1], v[3]] >> >>>>>>>>> ==>[v[4], v[5]] >> >>>>>>>>> ==>[v[4], v[3]] >> >>>>>>>>> ==>[v[6], v[3]] >> >>>>>>>>> >> >>>>>>>>> In the first result, the "tail/start/initial" is v[1] and the >> >>>>>>>>> "head/end/terminal" is v[3]. That lines up with the tail/head >> >>>>>>> terminology >> >>>>>>>>> in graph theory. However, what is off is that Pop.head/tail is >> >> wrong: >> >>>>>>>>> >> >>>>>>>>> gremlin> g.V().as('a').out('created').as('a').select(head,'a') >> >>>>>>>>> ==>v[1] >> >>>>>>>>> ==>v[4] >> >>>>>>>>> ==>v[4] >> >>>>>>>>> ==>v[6] >> >>>>>>>>> >> >>>>>>>>> Pop.head should return v[3] (for the first result). This is a >> >> simple >> >>>>>>> fix >> >>>>>>>>> of just reversing the meaning of Pop.head/tail (2 line fix). >> >>>>>>>>> >> >>>>>>>>> However, the reason you flipped Pop.head/tail to begin with is >> >>>> because >> >>>>>>> you >> >>>>>>>>> wanted it to align with unfold().tail(). So lets look at >> unfold(). >> >>>>>>>>> >> >>>>>>>>> gremlin> >> >>>>>>> g.V().as('a').out('created').as('a').select('a').limit(1).unfold() >> >>>>>>>>> ==>v[1] >> >>>>>>>>> ==>v[3] >> >>>>>>>>> gremlin> >> >>>>>>>>> >> >>>>>>> >> >>>> >> >> >> g.V().as('a').out('created').as('a').select('a').limit(1).unfold().tail(1) >> >>>>>>>>> ==>v[3] >> >>>>>>>>> >> >>>>>>>>> This should emit v[1]. Bumskies! However, this is about how the >> >>>>>>> "unfolded" >> >>>>>>>>> Iterable is iterated. >> >>>>>>>>> >> >>>>>>>>> gremlin> [1,2,3,4].iterator() >> >>>>>>>>> ==>1 >> >>>>>>>>> ==>2 >> >>>>>>>>> ==>3 >> >>>>>>>>> ==>4 >> >>>>>>>>> >> >>>>>>>>> Unfortunately, when you do List.iterator(), it emits values >> >>>>>>> left-to-right >> >>>>>>>>> (tail to head). Not right-to-left (head to tail). So, we can >> make >> >>>>>>> unfold() >> >>>>>>>>> behave differently by: >> >>>>>>>>> >> >>>>>>>>> gremlin> [1,2,3,4].reverse().iterator() >> >>>>>>>>> ==>4 >> >>>>>>>>> ==>3 >> >>>>>>>>> ==>2 >> >>>>>>>>> ==>1 >> >>>>>>>>> >> >>>>>>>>> …but that is no bueno from a memory conservation standpoint. I >> >> would >> >>>>>>> argue >> >>>>>>>>> that unfold() has nothing to do with path-semantics, but >> instead, >> >>>> list >> >>>>>>>>> semantics. Therefore, we can argue (in debate) that >> >> "unfold().tail()" >> >>>>>>> is >> >>>>>>>>> not an anomaly of tail(), but one of unfold(). >> >>>>>>>>> >> >>>>>>>>> Thus, to be consistent throughout, all we need to do is flip >> >> Pop.head >> >>>>>>> to >> >>>>>>>>> Pop.tail and vice versa (i.e. as it was originally). >> >>>>>>>>> >> >>>>>>>>> Thoughts?, >> >>>>>>>>> Marko. >> >>>>>>>>> >> >>>>>>>>> http://markorodriguez.com >> >>>>>>>>> >> >>>>>>>>> On Jun 12, 2015, at 12:56 PM, Matt Frantz < >> >>>> [email protected]> >> >>>>>>>>> wrote: >> >>>>>>>>> >> >>>>>>>>>> We could do any of the following: >> >>>>>>>>>> >> >>>>>>>>>> - Rename the "tail" step (e.g. "last") so that we can flip Pop >> >> back >> >>>>>>> to >> >>>>>>>>>> the way graph theorists presumably expect it to work. >> >>>>>>>>>> - Reverse the way "select" puts things in a List, and flip Pop >> >> back. >> >>>>>>>>>> - Rename Pop head/tail to oldest/newest (or first/last) >> >>>>>>>>>> >> >>>>>>>>>> >> >>>>>>>>>> On Fri, Jun 12, 2015 at 5:14 AM, Marko Rodriguez < >> >>>>>>> [email protected]> >> >>>>>>>>>> wrote: >> >>>>>>>>>> >> >>>>>>>>>>> Hm… I see what you are saying. The problem is that in graph >> >> theory, >> >>>>>>>>>>> head/tail terms are reversed in Path. >> >>>>>>>>>>> >> >>>>>>>>>>> Marko. >> >>>>>>>>>>> >> >>>>>>>>>>> http://markorodriguez.com >> >>>>>>>>>>> >> >>>>>>>>>>> On Jun 11, 2015, at 3:39 PM, Matt Frantz < >> >>>> [email protected] >> >>>>>>>> >> >>>>>>>>>>> wrote: >> >>>>>>>>>>> >> >>>>>>>>>>>> Another symmetry I was aiming for: >> >>>>>>>>>>>> >> >>>>>>>>>>>> ...select(tail, 'a') >> >>>>>>>>>>>> ...select('a').by(unfold.tail(1)) >> >>>>>>>>>>>> >> >>>>>>>>>>>> On Thu, Jun 11, 2015 at 2:16 PM, Matt Frantz < >> >>>>>>>>> [email protected] >> >>>>>>>>>>>> >> >>>>>>>>>>>> wrote: >> >>>>>>>>>>>> >> >>>>>>>>>>>>> I was trying to reconcile the way that the range/limit/tail >> >> steps >> >>>>>>>>>>> operate >> >>>>>>>>>>>>> with how Pop is interpreted. For local scope, the range >> >> ordinals >> >>>>>>> are >> >>>>>>>>>>>>> congruent with the list index ordinals. Thus, "limit(1)" >> means >> >>>>>>>>>>>>> "range(0,1)" which means List.get(0). Since "tail(1)" is >> the >> >>>>>>>>>>> complement of >> >>>>>>>>>>>>> "limit(1)", it means "the highest numbered element" or >> >>>>>>>>>>>>> List.get(List.size()-1). >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> I understand your description of a stream, but I was trying >> to >> >>>>>>>>> reconcile >> >>>>>>>>>>>>> the terms with Gremlin and not with streams. >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> If you compare a stream with a Unix command line, and how >> the >> >>>>>>> "head" >> >>>>>>>>> and >> >>>>>>>>>>>>> "tail" utilities act, then "head" means "the first lines you >> >> see" >> >>>>>>> and >> >>>>>>>>>>>>> "tail" means "the last lines you see". >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> For global scope, it seems that "limit(1)" means "the first >> >>>>>>> traverser" >> >>>>>>>>>>> and >> >>>>>>>>>>>>> "tail(1)" means "the last traverser". For any Traversal, t, >> >>>>>>>>> t.limit(1) >> >>>>>>>>>>>>> produces the same thing as t.toList().get(0). >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> Good news on select(pop)! >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> On Thu, Jun 11, 2015 at 11:43 AM, Marko Rodriguez < >> >>>>>>>>> [email protected] >> >>>>>>>>>>>> >> >>>>>>>>>>>>> wrote: >> >>>>>>>>>>>>> >> >>>>>>>>>>>>>> Hey, >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> Yes -- "first = tail" and "last = head". >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> A path grows with its "head growing" .. its tail is static. >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> a-->b-->c-->d-->e >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> the tail is always "a"…the head is "a", then "b", then "c", >> >> then >> >>>>>>>>> "d"…. >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> In a list or stream, the tail is the first element. >> >>>>>>>>>>>>>> - get(0) for list >> >>>>>>>>>>>>>> - stream().toList().get(0) >> >>>>>>>>>>>>>> In a list or stream, the head is always the most current >> >>>> element. >> >>>>>>>>>>>>>> - get(list.size() - 1) for list >> >>>>>>>>>>>>>> - stream().next() >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> …..? >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> I will hide your interface inside ImmutablePath just for my >> >>>> sanity >> >>>>>>>>> :). >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> BTW: select(pop) is on its way. >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> Marko. >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> http://markorodriguez.com >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> On Jun 11, 2015, at 12:30 PM, Matt Frantz < >> >>>>>>>>> [email protected]> >> >>>>>>>>>>>>>> wrote: >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> limit(1) means "first" and tail(1) means "last" (in both >> >> global >> >>>>>>> and >> >>>>>>>>>>>>>> local >> >>>>>>>>>>>>>>> manifestations). >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> In the Path.get results, you get a list whose first >> element >> >> is >> >>>>>>> the >> >>>>>>>>>>>>>>> first/oldest object matching the step label, so that felt >> >> like >> >>>>>>>>> "head" >> >>>>>>>>>>> to >> >>>>>>>>>>>>>>> me, while the last element is the most recent and thus >> >> "tail". >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> get => [a,b,c,d] >> >>>>>>>>>>>>>>> getSingle(head) => a >> >>>>>>>>>>>>>>> getSingle(tail) => d >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> In other words the following should be equal: >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> ...map{it->it.path().get('foo')}.tail(local, 1) >> >>>>>>>>>>>>>>> ...map{it->it.path().getSingle(tail, 'foo')} >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> I used ImmutablePathImpl because I needed HeadPath to have >> >> the >> >>>>>>>>>>>>>>> getSingleTail/getSingleHead methods, too. Thus, a common >> >>>>>>> interface >> >>>>>>>>>>>>>> between >> >>>>>>>>>>>>>>> ImmutablePath and HeadPath was required. The interface >> has >> >>>>>>> package >> >>>>>>>>>>>>>> scope, >> >>>>>>>>>>>>>>> so it is not part of the public API. >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> On Thu, Jun 11, 2015 at 11:12 AM, Marko Rodriguez < >> >>>>>>>>>>> [email protected] >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>> wrote: >> >>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> Hi Matt, >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> limit(1) means the most recent value. >> >>>>>>>>>>>>>>>> tail(1) means the oldest value. ? >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> path: [a,b,c,d] >> >>>>>>>>>>>>>>>> a = tail >> >>>>>>>>>>>>>>>> d = head >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> No? >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> Also, why did you do ImmutablePathImpl? Seems that can >> just >> >> be >> >>>>>>>>>>> private >> >>>>>>>>>>>>>>>> methods inside of ImmutablePath? >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> Thanks, >> >>>>>>>>>>>>>>>> Marko. >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> http://markorodriguez.com >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> On Jun 11, 2015, at 11:56 AM, mhfrantz < >> [email protected]> >> >>>>>>> wrote: >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> GitHub user mhfrantz opened a pull request: >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> https://github.com/apache/incubator-tinkerpop/pull/76 >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> TINKERPOP3-700 Path getSingle/getList improvements >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> As requested in the comments of TINKERPOP3-700. I also >> >>>>>>> reversed >> >>>>>>>>>>> the >> >>>>>>>>>>>>>>>> sense of `Pop` to align with `tail(local)`. Thus >> `Pop.tail` >> >>>> now >> >>>>>>>>>>> means >> >>>>>>>>>>>>>> the >> >>>>>>>>>>>>>>>> most recent value. >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> You can merge this pull request into a Git repository by >> >>>>>>> running: >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> $ git pull >> >> https://github.com/RedSeal-co/incubator-tinkerpop >> >>>>>>>>>>>>>>>> TINKERPOP3-700-Path-getSingle >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> Alternatively you can review and apply these changes as >> the >> >>>>>>> patch >> >>>>>>>>>>> at: >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> >> >> https://github.com/apache/incubator-tinkerpop/pull/76.patch >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> To close this pull request, make a commit to your >> >>>> master/trunk >> >>>>>>>>>>> branch >> >>>>>>>>>>>>>>>>> with (at least) the following in the commit message: >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> This closes #76 >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> ---- >> >>>>>>>>>>>>>>>>> commit e1e1a40b068ffe6da3d321256d6200dee0504074 >> >>>>>>>>>>>>>>>>> Author: mhfrantz <[email protected]> >> >>>>>>>>>>>>>>>>> Date: 2015-06-11T16:47:41Z >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> Add javadoc for Path getList/getSingle >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> commit 4939cf0a22c4fc44a4f86ed3e023fa30e4e872cc >> >>>>>>>>>>>>>>>>> Author: mhfrantz <[email protected]> >> >>>>>>>>>>>>>>>>> Date: 2015-06-11T17:10:27Z >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> Reverse sense of Path.getSingle Pop to align with >> >> tail(local) >> >>>>>>> step >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> commit 027d6319f9ff06ca26d785e83bf17b21364c3dca >> >>>>>>>>>>>>>>>>> Author: mhfrantz <[email protected]> >> >>>>>>>>>>>>>>>>> Date: 2015-06-11T17:51:23Z >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> Optimize MutablePath.getSingle >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> commit 5e9ad8d7dff6c63b9746147a1d255cbf7258cea3 >> >>>>>>>>>>>>>>>>> Author: mhfrantz <[email protected]> >> >>>>>>>>>>>>>>>>> Date: 2015-06-11T17:52:43Z >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> Optimize ImmutablePath getSingle and getList >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> ---- >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>>> --- >> >>>>>>>>>>>>>>>>> If your project is set up for it, you can reply to this >> >> email >> >>>>>>> and >> >>>>>>>>>>> have >> >>>>>>>>>>>>>>>> your >> >>>>>>>>>>>>>>>>> reply appear on GitHub as well. If your project does not >> >> have >> >>>>>>> this >> >>>>>>>>>>>>>>>> feature >> >>>>>>>>>>>>>>>>> enabled and wishes so, or if the feature is enabled but >> not >> >>>>>>>>> working, >> >>>>>>>>>>>>>>>> please >> >>>>>>>>>>>>>>>>> contact infrastructure at [email protected] or >> >> file >> >>>> a >> >>>>>>>>> JIRA >> >>>>>>>>>>>>>>>> ticket >> >>>>>>>>>>>>>>>>> with INFRA. >> >>>>>>>>>>>>>>>>> --- >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>>>> >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>>> >> >>>>>>>>>>>>> >> >>>>>>>>>>> >> >>>>>>>>>>> >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>> >> >>>>>>> >> >>>>>> >> >>>> >> >>>> >> >> >> >> >> >> >
