#Depedancy Discussion
1 messages · Page 1 of 1 (latest)
🧵
🪡
Convo starts here for anyone finding the thread later #💻・modding-dev message
so if we stick to CNF in dependencies [a,b|c,d -> a and (b or c) and d] and treat conflicts separately as each entry negated, that still means they would be fundamentally chained with OR
right?
Alternative idea
we get rid of more complicated thingas
and do an array for the main operator (AND for deps, OR For anti deps)
and then the other dep is just in that
NOT (a OR b OR ...) for anti deps right
so something like dependencies: [ "A", "B>=2|C", "D<=2"], conflicts: ["E,F>=1", "G"]
so json { "Deps": [ "Talisman>=1.0", "Steamodded>=1.0~", "Steamodded>=1.0~beta-9999a OR AlternativeDep>=1.0", ], "Conflicts": [ "Cryptid<=1.0" ] }
Not sure exactly what do for an and in conflicts
the OR is subject to be changed
where that means the mod conflicts with the combination of E and F>=1 and also conflicts with G
definitely not a literal OR
I think with this solution, | for alternative deps and & for chained conflicts
Do we even need chained conflicts?
maybe chained conflicts are just stupid
if you can't load if both A and B are present but are fine with either one on its own, what are you doing
Would they be useful for conflicting with a version range for a conflict
like if I want to conflict with versions >=2.0 and <3.0
how would I do that?
can't I just supply a version range like "Cryptid>=2.0<3.0"
that's how this has been working with dep strings
except we don't have strict inequalities
I'd prefer to write it as 2.0 <= Cryptid < 3.0 but sure
Cause I think conflicting only if 2 packages exist is kinda silly
cut that part, not sure what I was thinking that was useful for
Maybe a way for mods to show up as failed to load in thier code (assumingthey haven't registered anything yet)
So this is what we are thinking for syntax? JSON { "Deps": [ "Talisman>=1.0", "Steamodded>=1.0~", "Steamodded>=1.0~beta-9999a | AlternativeDep>=1.0", ], "Conflicts": [ "Cryptid<=1.0", "DebugPlus>=2.0<3.0" ] }
also possible alternative json { "Deps": [ "Talisman>=1.0", "Steamodded>=1.0~", [ "Steamodded>=1.0~beta-9999a", "AlternativeDep>=1.0" ] ], "Conflicts": [ "Cryptid<=1.0", "DebugPlus>=2.0<3.0" ] }
I feel like thats not clear enough
that looks confusing
first one is clearer
This would be interpreted as
Depends on Talisman>=1.0 AND Steamodded>=1.0~ AND (Steamodded>=1.0~beta-9999a OR AlternativeDep>=1.0)
Conflict with Cryptid<=1.0 AND DebugPlus Between 2.0 up to (not including) 3.0
Yeah I don't like the sub array either
Maybe we should do a debain and do json { "Deps": [ "Talisman (>=1.0)", "Steamodded (>=1.0~)", "Steamodded (>=1.0~beta-9999a) | AlternativeDep (>=1.0)" ], "Conflicts": [ "Cryptid (<=1.0)", "DebugPlus (>=2.0) (<3.0)" ] } (Not sure how to handle the last case)
oh wait thats the wrong base example
Edited
I'm still not a huge fan of chaining the version relations like >2.0<3.0
though the brackets help
The issue is parsing 1.0 < pkg is a lot hearder to parse
cause now we got to figure out if 1.0 is a id or version
I guess brackets still help here
but then it's still a bit more complicated
Also since we need to parse this
fair
what is allowed in version string and id strings
if we do brackets, neither are allowed brackets
I propose [A-Za-z0-9._~-] for both
(although I also purpose % or smth be allowed to be the first char for internal id's only)
don't forget the .
right
parsing the versions without brackets works alright, I still think I prefer them
(so we can provide a %balatro package and you can do %balatro (=1.0.1m-FULL))
It would just be prohibited in the id and the provides
as of now that's only balatro and lovely right (possibly steamodded?)
Same with a %lovely for lovely itself, possible a %SMODS or %steamodded and then also the lovely only mods won't cause conflicts
potential to prohibit any characters that can't be indexed like SMODS.Mods.IDGOESHERE in the id
Yeah probably
This would remove .~-
could also do != instead of ~=
do we need a not eqal?
I'd leave out not equal
Doesn't make sense for deps and for conflicts just depend that exact version
besides you could already do that with > and <
I did notice debain does << and >> for the < >
that's convenient because the operator is always two chars
yeah
I'd take that
also less likely for mistakes by typo
eh, feels cumbersome
What are you wanting to use ~= for?
Proposed operators A (>=1.0) - A greater than or equal to 1.0 A (<=1.0) - A lesser than or equal to 1.0 A (>>1.0) - A greater than to 1.0 A (<<1.0) - A lesser than to 1.0 A (==1.0) - A equal to 1.0 (would this also match 1.0.0? Would A==1.0.0 match A 1.0 as well?)
1.0 and 1.0.0 are internally the same version
unless you fill missing fields with -1
ok that makes sense to me
which we don't
I'm assuming 1.0 and 1.0~ don't match
I guess it'd be like getting into the negation operators again, and yeah you can just swap between deps and anti-deps, that's way better than ~=
Should I ping mathisfun? I feel like he would have some potentially useful insite
go for it
yes
@jovial hawk got any thoughts?
in fact 1.0~ is the least version of major 1 and minor 0
meanwhile I wrote up this conversion
Yeah that makes sense
aka we're a bucnh of developer
a version can't start with = in our system so it's not actually ambiguous, just more annoying to parse
yeah I was mostly thinking about parsing
also I'd propose all white space is just ignored
people will keep asking this btw
What if we added an ===?
==1.0 matches 1.0.x, ===1.0 only matches 1.0.0
Making > and < aliases is probably better for ease of use
yes there's another mistake in here (i used v over part)
And just warn the user
If they’re not using << or >>
TBH I don't think a package should ever have one version as 1.0 and one as 1.0.0
could also do it as >= 1.0 and < 1.1?
Well that matches 1.0.1
this sounds like javascript hell
i think that's too confusing
Oh wait your suggesting it matches only the sub version
So you can match any 1.x.x
That might be worth considering
that would require 1, 1.0 and 1.0.0 to all be different versions internally
which they're not
Not what I'm suggesting
I'm on mobile give me a minute to get back to my dorm to type something up
imo that's too much work for something you can already do
The thought is some kind of operator where it would basically convert (newOperator A.B.C) to (>= A.B.C) (< A+1.0.0)
Oh also thought does <1.0.0 still match 1.0.0~
Also possibly the same op but (>= A.B.C) (< A.B+1.0)
ah
Mostly cause I suspect that a lot of people are just going to do >= version and then break when major version change
yes. so (newOperator A.B.C) ~> (>= A.B.C) (< A+1.0.0~) maybe
yeah that makes sense
Although it gets potentially messy if you want to support multiple major versions
Maybe we just well document what to do
wait >= 1.0.0 wouldn't match 1.1.0?
no it does
The idea is if you want to match just 1.x versions we might want an operator to help with it
¯_(ツ)_/¯
ah
Wild card?
could == 1.1 work for that?
1.*
just had the same thought lmao
should we make (<= 1.0) and (<< 1.0) actually match 1.0~?
Cause I doubt most people actually want < 1.0
yes, that's how the ordering works
we just put in the docs that the wanted behavior is <<1.0~
sorry like behave like the user put 1.0~
well
I gues it would just be <<
<= would match as expected
Cause if I put << 1.0 I wouldn't expect 1.0~beta1 to match
and lets be honest people aren't going to read the docs they'll jsut look at a couple exaples from other mods
We could add some other thing to force the actuall 1.0
like 1.0! or smth
Yeah I can't think of any case where one would want to match ~ versions but not the main version they are based off of, other than if you just want to match the ~ versions
Maybe we could make << 1.0 behave as << 1.0~ and add a <~ or smth that behaves as << 1.0
surely they'd be the other way round, no?
well the behaviour I described for << would be the intended behaviour in most cases
so it would make more sense to me to make it the << operator
oh nvm I am dumb and forgot ~ is for pre 1.0
it seems this works for the most part
just need to make sure I didn't break stuff by allowing major-only versions
i did find this which is a bit weird
I think tralining .'s shouldn't be allowed
I would have kept it that way if I could just use regex
i can't figure out how to do that with a lua pattern
maybe some string.gmatch can help
how strict are we on the spec?
cause you could just require %d+(\.%d+(\.%d+)?)?[-~]
I probably messed that up somehow
I guess that wouldn't work with balatro's versions as it has a letter right after the last number
I'm not sure lua patterns can even nest captures
rn I'm at ^(%d+)%.?(%d*)%.?(%d*)(.*)$ which is definitely not restrictive enough
put the .'s in the capture group for the mnumber they go with
will have to do some more work to remove it from the group but thats another simple pattern
unless it supports non-captruing grouops
it doesn't
Oh this will be handy once you get to the bracket part
oh i don't need this, we don't support nested brackets
regex at 12:30 is never a good idea
almost regex at 12:30 is never a good idea
anyways I pushed what I have up to a temp branch
if anyone wants to fix the version string pattern, be my guest
because I shall go to sleep
also the dependency checker might need some further testing for I won't trust code I wrote past midnight
I might be stupid
can't figure out how to print the captures
I'm doing
eval for m in string.gmatch("1.0.1", "^(%d+)%.?(%d*)%.?(%d*)(.*)$") do
print(m)
end```
but its not priting anyrthing
ok wtd
for m in string.gmatch("1.0.1", "(%d+)") do
print(m)
end
``` prints something but ```lua
for m in string.gmatch("1.0.1", "^(%d+)") do
print(m)
end
``` doesn't
oh I can string.match
can't make groups optional
thats annoying
wtf?
oh, that's what went wrong
you can detect the trailing dot and then just erorr manually
like my (WIP) pattern ^(%d+)(%.?(%d*))(%.?(%d*)) you get two groups for the digit so if one is empty and one isn't its an error
so you can detect the traling dot in the last case
Here it is with the rest
I'm assuming we stick the last group through another regex
^(%d+)(%.?(%d*))(%.?(%d*))(.*)$
oh I posted two sets of them in the scvreenshot
I'm assuming we want to parse this as it has
I'll push my test setup so you all can use it to
let me know if you guys need any help, I've got experience with this sorta thing
my general heads up is that the more feature-filled dependency resolution becomes the slower and more complicated it gets
makes sense
if you want version ranges and incompat then I 100% recommend implementing this as a directed graph
you can do a graph traversal to determine your dependency set AND do advanced analysis on the graph
oh no data structures and algorithms my only weakness
this is neither battle tested nor is it fully featured but this my wip package dependency resolver for tcli https://github.com/thunderstore-io/tcli-rust/blob/develop/src/package/resolver.rs
not inside the version class imo. it should just return a version that isn't considered valid (maybe -1.0.0?) we can then throw errors as needed elsewhere or replace with 0.0.0
for deps it should at least give a warning
will consider if/when there's any advanced analysis to be done
I'm already using DFS so I'm not gonna rewrite just because
that's fair. Although, I'm not sure how to propogate the error to the user in that case
Also you should mess around with the test file cause I need to force people to test stuff for me
hm yeah
thoughts on this?
I think no but its kinda tricky
if no, what wildcard is supposed to match it?
great question
see the issue is if I specify I want a 1.* version and geting a prerelease 1.0 version is almost never what I want
steamodded is the big exception
maybe 1.*~
(==1.*) (>=1)
yeah that's my other concern, this is confusing and inconsistent
I'm almost worndering if maybe we should never match a ~ build unless the user manually specifies
and then allow appending ~ as a shorthand to match any ~ version as well
I'm just thinking index wise auto downloading beta versions is a bad idea
hm
I know in my case beta versions are not goign to always match the api of a full version
this has no correlation (yet) to how the index would auto download versions
well it does somewhat
I think it would be fair to say >= 1.0~ will match all 1.0 versions inclduing beta
or == 1.*~ will match all 1.x versions including betas (but == 1.* won't match 1.1~ for example)
yeah that's what I was just thinking
I think a ~ without any content should have special meaning
make it where a real version can't have it
but when resolving deps it will match any beta version
not sure should (== 1.0~ match 1.0)?
no
no
ok makes sense to me
looks good
was just thinking if we did want empty ~ we could also allow wildcard ones
should (<<1.1) and (<=1.1) match:
- 1.1~x
- 1.0.1~x
I'm thinking no
what about (<<1.1~) and (<=1.1~)
I'm thinking yes
technically 1.1~ would be the least 1.1 version
I think this should be a special case
but since this matches all beta 1.1s, this makes sense
there's no difference between <<1.1~ and <=1.1~ then?
technically I have not considered wildcards for use with << at all
we're treating just ~ as a wildcard basically
Im referring to * as wildcard here
<<1.* would behave like <<2 so it's fully redundant
so is <=1.*
arguably we only need to allow * for use with ==
yeah
=1.* is just >=1, while >>1.* is >>1
lemme see
I didn't account for * wildcards in strict inequalities
1.* is represented as 1.-2.0, so <=1.* is actually equivalent to <<1
Agree with Wilson, <=1.* shouldn't exclude 1.*
I think I'd still prefer if they made sense
yeah it does seem odd having a version that can only be represented with one operator
I think it should just be the same as <<1.0
if * represents "all applicable versions at once", it should just mean <<1
likewise >>1.* should refer to >=2 then?
yeah
that one I can see making sense
cause if your like a need a version higher than version 1
so >=1.* means >=1 because ==1.* does that and >> is a subset of it
yeah
likewise <=1.* is like <<2
yeah
Makes the most sense to me yeah
and all of this can only ever match if beta-ness is equal, or do we have exceptions to that?
yeah right
but if >=1.0~ matches non-betas, by extension <=1.0 must also match betas
else we don't have a well defined relation
=1.0 doesn't match betas, that's not what I said
I'm saying if >=1.0~ will match 1.0, then <=1.0 must match 1.0~beta
else it's not really an ordering at all and operator overloading can't handle it
<= is a silly operator
idk
since this is for dependencies, I don't think you should match betas unless specifically required
as a user, I'm not sure I'd expect a beta to be installed when using >= 1.0
a 1.0.1 beta likely doesn't have breaking changes from 1.0.0 stable
yeah I figured the same
although technically a 1.1.0 beta could behave differently than 1.1.0 stable
cause the feature thats added may change betwene the two builds
hence why (>=1.1) does not include any 1.1.0 beta (or any beta at all, for that matter)
but (>=1.1~) might include a 1.1.0 stable and a 1.1.1 beta
oh nevermind I'm being inconsistent
if (==1.*~) matches all 1.x including betas, (==1.0~) should match all 1.0 including betas
alright I think I got it down
who needs a total ordering anyways
would appreciate some more testing on this
I'll add some of the other stuff like a config file name, icon atlas metadata and making provides usable with this, then we'll be pretty much set for a beta release with this merged