-
Notifications
You must be signed in to change notification settings - Fork 1
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
spec for Go app to invoke path/filepath APIs #1
Comments
Its fine to use stdin and stdout. The inputs and outputs would systematically follow the go API arguments and the result type it returns. So the code I write to use this API will just call This way I can also just write regular XUnit unit tests that are straightforward to port. I certainly do hope to be able to produce bug fixes, since I will show that standard calls will always fail in certain situations -- the changes I will introduce well they might not yield a path like novice Windows users would be wrongfully expecting (C:...) but they will not crash programs that crash today. |
Let me type that spec over here.
So to provide a few examples:
And the result is an anonymous
Responded to with:
Responded to with:
|
We will finally for It is probably enough to have just one or two, one that counts the number of results and writes that as the result to the call and one that simply dumps the full path of every item. This serializes as
Which immediately writes:
then outputs any output implemented by the actual
etc, then optionally summaries if defined, e.g. for
then result value of the call
|
Lets change the prefix and suffix for commands. From prefix |
Since you want name/value pairs, let's format input and output as JSON objects. That's easy to do in Go. I don't want to re-invent parsing. Any command taking a variable list of arguments would be formatted as an array, even if a single argument is supplied. Is WalkFunc an API to call on each node in a filesystem tree? If not, what does it provide the calling script? |
Well JSON is messy for humans and the parsing needed is very basic. Plus, JSON breaks down for WalkFunc - it is supposed to write to the console in a streaming fashion. No |
Plus there can be times some calls take very long or the process crashes, in which case I am not sure I will receive end of stream or what will happen, so I might have to go async and define timeouts, which also complicates parsing if it is not purely on a line-by-line basis. |
So the point of Walk is to stream FileInfo objects from a dir? Do you need fields in them besides Name() & IsDir()? I still don't follow the uses of Walk. Pls tell me what it does and why. I can stream separate JSON objects or strings and you can decode them a line at a time. If you want human-writable inputs to your script, you can parse them with PS and generate JSON for me. I am just an AI, sorry. |
Mmm, yeah look here. It does what you expect, plus it eats error codes while doing it and sorts each directories contents by name and calls |
At this time I don't see use for Even |
OK, working on first draft... |
I am not sure C# will give me tuple element names for type parameters. Can we standardize on a result named
for any result that has tuple type That is for Both |
And just to be explicit, with JSON it'd become. Call { "Name": "IsAbs", "args": { "path": "C:" } } Response { "Name": "IsAbs", "result": true } Or if the result is a tuple { "Name": "Glob", "result": { "matches": [ "foo.txt" ], "err": null } } or { "Name": "Abs", "result": { "result": [ "C:\\path" ], "err": { "Error": "Huh, both!?", "Code": null } } } Calling Call: { "Name": "Walk", "args": { "root": "C:\\", "walkFn": "DefaultWalk" } } Immediate response: { "Name": "Walk" } Then a stream of:
well assuming And finally: { "Name": "Walk", "result": { "Error": "What could this ever be?", "Code": null } } If it can happen both a result is not empty and the error is not null, then I would prefer receiving
|
It would be more efficient to do |
Remember, no battle plan survives first contact with the AInemy :-) Posted a draft; tested on Linux only for the moment. |
I'd suggest you parse the user-crafted input into a struct in powershell, and convert it to JSON (PS can do that?) when ready to send to stdout. It's probably best to avoid a C# build step in the go builder instance that will run these tests. I don't see why you'd need the api name in the output, but could add that. |
No its ok like this - not sure why you added It is awful to type PS> "{ ""Api"": ""path.filepath.IsAbs"", ""Path"": ""$($PWD.Path.Replace("\", "\\"))"" }" | .\go.exe
{"Errno":0,"Result":true} or PS> "{ ""Api"": ""path.filepath.IsAbs"", ""Path"": ""\\\\?\\Volume{607932d3-78af-41c0-9786-dd0177e78a39}"" }" | .\go.exe
{"Errno":0,"Result":false} but there is the first bug. and quite involved when having PS do it Get-Partition -DiskNumber 6 -PartitionNumber 2 |
select -ExpandProperty AccessPaths |
where { $_.StartsWith("\\") } |
foreach { [pscustomobject]@{ Api = "path.filepath.Walk"; Path = $_ } } |
foreach { "$($_ | ConvertTo-Json)".Replace("`r`n", "") } |
foreach { $_ | .\go.exe |
foreach { $_ | ConvertFrom-Json } } but this API is fine with the volume path. |
Heck here you go with the string manipulations PS> "{ ""Api"": ""path.filepath.IsAbs"", ""Path"": ""C:"" }" | .\go.exe
{"Errno":0,"Result":false} |
No these API's are OK; they refer to the current working directory on that volume. |
This is absolutely wrong PS> "{ ""Api"": ""path.filepath.Abs"", ""Path"": ""\\\\?\\."" }" | .\go.exe
{"Errno":0,"Result":"\\?"} And if the above is OK then this is certainly not PS> cd Y:\Source
PS> C:
PS> "{ ""Api"": ""path.filepath.Abs"", ""Path"": ""Y:"" }" | .\go.exe
{"Errno":0,"Result":"Y:\\"} |
"{ ""Api"": ""path.filepath.Walk"", ""Path"": ""\\\\?\\Volume{607932d3-78af-41c0-9786-dd0177e78a39}"" }" | .\go.exe
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x30 pc=0x4dd9fe]
goroutine 1 [running]:
main.walkInfo(0xc0000b6060, 0x30, 0x0, 0x0, 0x53b220, 0xc0000b8420, 0xc000096440, 0x0)
C:/Users/Eric/Source/Repos/GoWindows/src/go/api.go:58 +0x3e
path/filepath.Walk(0xc0000b6060, 0x30, 0x51f1d0, 0x1, 0x0)
C:/tools/go/src/path/filepath/path.go:404 +0x71
main.main()
C:/Users/Eric/Source/Repos/GoWindows/src/go/api.go:37 +0x3f1 |
If that is caused by an error from the go API it is still wrong. |
And I expect it to enumerate all of |
Pls lets document Go API bugs in a different thread! This is about my api app! |
You're the best 🥇 |
But yeah I guess |
The panic you found in Walk is because the FileInfo is null, I think. I'll fix that in next rev. If Walk encounters an error, it will be reported as an error result. Any more requests re input & output defs? My next step is to add the rest of the filepath functions... Doesn't PS have an alternate quoting feature (e.g. here-doc) so you don't have to escape |
Well, I guess this is mostly OK. I had the idea to put it all in C# such that I can run Xunit, but maybe that is only needed for the C# that I'd write. I might have to spawn a lot of processes depending on what the tests will end up to be, but hey that's the unix way I guess. |
https://en.wikipedia.org/wiki/Here_document I could make the app loop on stdin if that's helpful. You'd prob only need to do Walk with a sep process. That would let you redirect stdin from a file, and and then diff the output with expected (hardcoded) results. |
Yes, but then I would also need some kind of separator at least for
|
And having followed your fine example and putting the assignment to PS> '{ "Api": "path.filepath.Walk", "Path": "\\\\?\\Volume{607932d3-78af-41c0-9786-dd0177e78a39}" }' | .\go.exe
{"Error":"GetFileInformationByHandle \\\\?\\Volume{607932d3-78af-41c0-9786-dd0177e78a39}: Incorrect function.","Errno":-222,"Result":"\\\\?\\Volume{607932d3-78af-41c0-9786-dd0177e78a39}"} |
Oh yeah and how can I make the executable not be named |
I've updated the code to loop on stdin and fix Walk. No more APIs yet. |
And now I've added the rest of the filepath functions. Also changed api names to EDIT: I think you can use |
Yes, good trick. It works quite well even from the PowerShell command line. I was worrying it might stay open but it neatly exits. PS> '{ "Api": "filepath.Abs", "Path": "." }{ "Api": "filepath.Abs", "Path": "." }' | .\api.exe
{"Errno":0,"Result":"C:\\GoWindows\\src\\go"}
{"Errno":0,"Result":"C:\\GoWindows\\src\\go"}
PS> and even PS>
>> @'
>> { "Api": "filepath.Abs", "Path": "." }
>> { "Api": "filepath.Abs", "Path": "." }
>> '@ | .\api.exe
{"Errno":0,"Result":"C:\\GoWindows\\src\\go"}
{"Errno":0,"Result":"C:\\GoWindows\\src\\go"}
PS> |
Mmm, this is a bit obfuscating: '{ "Api": "filepath.Separator"}' | .\api.exe
{"Errno":0,"Result":92}
PS> [char]92
\ Can you make that a string perhaps? And remove "filepath." from the "Api" parameter? It is just clutter at this time imho. |
You'll probably have to validate os APIs! I think the input is clearer with the package prefix. OK, can convert separators to strings. EDIT: done. |
Is this proper? I never get more than one element back. Get-GoFilePath -SplitList "C:\tools\GoWindows\src\go\api.exe".Replace("\", "/") -Verbose
VERBOSE: where api.exe returned 0: '' (File Exists: False)
VERBOSE: Looking for 'api.exe' in the current working directory 'C:\tools\GoWindows\src\go' since it was not found on the path.
VERBOSE: Using 'C:\tools\GoWindows\src\go\api.exe'.
VERBOSE: In-Json: { "Api": "filepath.SplitList", "Path": "C:/tools/GoWindows/src/go/api.exe"}
VERBOSE: Out-Json: {"Errno":0,"Result":["C:/tools/GoWindows/src/go/api.exe"]}
Errno Result
----- ------
0 {C:/tools/GoWindows/src/go/api.exe} |
Oh, wait, I get it. PS> Get-GoFilePath -SplitList $env:Path -Verbose | select -ExpandProperty Result
C:\WINDOWS\system32
C:\WINDOWS
(abbreviated) |
Check this GoFilePath PowerShell script. |
Hm, I was expecting a PS script with a collection of filepath API invocations demonstrating bugs, and PS commands illustrating correct results.
Should be: PowerShell You have one instance of I don't understand the "Use like so..." lines. Is that for Command Shell? Why is You don't mention starting powershell before |
I was working on that -- to do that from a clean machine. So I will be creating a .vhdx and a file share and map them in various ways before calling this function to verify the output.
Sorry, the readme has been typed quite hastily. I haven't gone through what is necessary to make it a PowerShell module, so I have just this one file that defines a single function. I have updated the readme a bit.
There is only one function and it is called |
Re the CL, you'll need to run You might be asked for other style changes. I use identifier prefixes, which most of the world has not discovered. We'd have to put those in the original. |
I think Liam might have answered my question in I am writing a console app like yours now - I believe I can make it a single file, shipping the .NET runtime with it. It will be large. It will still be fairly easy to make a PowerShell module (out of it). |
You think it's a coincidence that two Liam's are helping you? I make a nice cup of cocoa, will that do for "chocolate"? I think cinnamon will be better in it than C# tho. That code example is in the go/ folder here. But I don't think including .NET in a CL is reasonable. We can probably get a builder configured for it. Maybe we should wait til 1.15 is out; they seem preoccupied with that. |
Maybe the code I write is just proof of what is possible and what is wrong with go such that it is enough to have your go app and a bunch of data in the go repo eventually. |
Not even a "LOL" for my efforts! :'( Hm, maybe api.exe needs tInput.Expected, and to compare that with tOutput. |
!? Your effects will be used, mine might evaporate.
Not really. Windows comes with PowerShell. Guaranteed, except for Nanoserver containers. |
But simpler to do the comparison in Go, and bundle expected results with input. Re efforts, I was referring to my joke after you separated me from golang-dev Liam, and asked for chocolate. Re-read the thread! |
Oww that is iffy of me lol, yeah ok well thanks for responding I guess 8) I just had in my mind from the start that it was probably someone who had responded in one of the issues where I was involved, but since you don't use your name there and the others have names that I hadn't remembered yet..... |
How do I rewrite Well better yet, how do I make this compile against my fork, before pushing to it:
I assume
|
The error means a function literal signature doesn't match a named Docker CLI source may import other files via github.com/docker/cli/... (or docker.com/git/cli/...?) Try moving your fork (with whole CLI repo) to GOPATH/github.com/docker/cli and then
|
Life is good without $P$G> cmd /c mklink /j C:\Users\Eric\go\src\github.com\docker C:\Users\Eric\Source\GitHub\docker
$P$G> hello
API server listening at: 127.0.0.1:19399
Chdir [<nil>] \\?\Volume{7bbce513-361b-4ff4-aedb-09499749192a}\ =>
Getwd [<nil>] \\?\Volume{7bbce513-361b-4ff4-aedb-09499749192a}\ => \\?\Volume{7bbce513-361b-4ff4-aedb-09499749192a}
Abs [<nil>] C:\go\Peculiar\Junction\Peculiar\Docker => C:\go\Peculiar\Junction\Peculiar\Docker
Abs [nul] C:\go\Peculiar\Junction\Peculiar\Docker => C:\go\Peculiar\Junction\Peculiar
EvalSymlinks [EvalSymlinks: too many links] C:\go\Peculiar\Junction\Peculiar\Docker =>
IsAbs [<nil>] C:\go\Peculiar\Junction\Peculiar\Docker => true
VolumeName [<nil>] C:\go\Peculiar\Junction\Peculiar\Docker => C:
ResolveAndValidateContextPath [readlink C:\go\Peculiar\Junction\Peculiar: The file or directory is not a reparse point.] C:\go\Peculiar\Junction\Peculiar\Docker =>
ResolveAndValidateContextPath [<nil>] C:\go\Peculiar\Junction\Peculiar\Docker => C:\go\Peculiar\Junction\Peculiar\Docker
GetContextFromLocalDir [<nil>] C:\go\Peculiar\Junction\Peculiar\Docker => (C:\go\Peculiar\Junction\Peculiar\Docker, Dockerfile)
Process exiting with code: 0 |
Input: an API name & required arguments. From command line args or stdin?
Test input: a flag and output or error string; Go API not called.
Output: a pathname. To stdout?
Error: a Windows error code and associated Go string. To stderr?
Analysis: comparison of output with expected result lives in external script?
Process: do you expect to modify this Go code?
Note: I'm not sure that this effort will yield any bugfixes in Go. The Windows maintainer is not a Google employee, and has opposed bug reports and proposals on grounds that they could break existing programs, without giving real-world examples of such programs. The Go team is reluctant to overrule him. There are few active contributors to the Windows port to advocate fixes. We may only be able to get something added to x/sys/windows. Worst case, we'll have to publish a third-party package.
The text was updated successfully, but these errors were encountered: