Skip to content
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

Methods for object resolves #1224

Merged
merged 16 commits into from
May 18, 2023
Merged

Methods for object resolves #1224

merged 16 commits into from
May 18, 2023

Conversation

worksofliam
Copy link
Contributor

Changes

Adds new methods to help with resolving paths to source members and streamfiles.

Checklist

  • have tested my change
  • updated relevant documentation
  • Remove any/all console.logs I added
  • eslint is not complaining
  • have added myself to the contributors' list in CONTRIBUTING.md
  • for feature PRs: PR only includes one feature enhancement.

@worksofliam worksofliam changed the title Initial work for source member resolve Initial work for object resolves Apr 6, 2023
@worksofliam worksofliam changed the title Initial work for object resolves Methods for object resolves Apr 6, 2023
return undefined;
}

async streamfileResolve(name: string, directories: QsysPath[]): Promise<string|undefined> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edmundreinhardt @SanjulaGanepola Looks like there is no way to /usr/bin/find to take a list of file names.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking a look at the documentation, the find command supports the OR operator. I think we can handle a list of file names using this?

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SanjulaGanepola Thanks - that syntax works. Working on that now.

-bash-5.1$ /usr/bin/find /QSYS.LIB/LIAMA.LIB/QRPGLESRC.FILE/ /QSYS.LIB/LIAMA.LIB/QRPGLEREF.FILE -name 'BADEMPS.*' -o -name 'BANG.*'

@worksofliam worksofliam self-assigned this Apr 6, 2023
@worksofliam worksofliam marked this pull request as ready for review April 7, 2023 15:28
@worksofliam worksofliam requested review from SanjulaGanepola, sebjulliand and chrjorgensen and removed request for SanjulaGanepola April 7, 2023 15:28
@chrjorgensen
Copy link
Collaborator

@worksofliam Code looks good to me - but I have no way of testing this, since the new methods are not being called anywhere.

Btw, is this first step to make copy member resolution work like the RPG compiler? 🤞

@worksofliam
Copy link
Contributor Author

@chrjorgensen

Btw, is this first step to make copy member resolution work like the RPG compiler?

That's exactly right!

I do hope in the future we can write tests for this also. (#1179)

@worksofliam worksofliam removed their assignment Apr 7, 2023
@worksofliam
Copy link
Contributor Author

I have added tests for these new APIs.

@SanjulaGanepola Note that find searches IFS directories recursively.

@worksofliam worksofliam linked an issue Apr 10, 2023 that may be closed by this pull request
if (find) {
const command = [
find,
...directories,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to work out how we can get this to be non-recursive and only look in the directories provided.

https://unix.stackexchange.com/questions/372994/equivalent-maxdepth-for-find-in-aix

Copy link
Collaborator

@chrjorgensen chrjorgensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@worksofliam I think we're on the wrong track here...

You basically only want to check for whether some specific members exists.
This can easily be accomplished by a simple script:

for m in /QSYS.LIB/VSCODEIBMI.LIB/CCSID1147.FILE/MEMBER.MBR /QSYS.LIB/QGPL.LIB/CCSID1147.FILE/MEMBER.MBR;
do
  if [ -f $m ]
  then
    echo $m
  fi
done

This also works for streamfiles:

for m in /TMP/testing/subdir/test.SQL /tmp/testing/test.sql;
do
  if [ -f $m ]
  then
    echo $m
  fi
done

No need for find or any other utility...

Building the script can be done in a few lines - the list of files probably even in your favorite one-liners...! 😄

@worksofliam
Copy link
Contributor Author

@chrjorgensen There is a reason we're standardising here with these APIs - I don't want to write the same script in every extension (this will be used in RPGLE, CL, etc!)

Though that is very cool that you have figured out how to keep it simple - how do think we could go about using your idea inside of our API without find?

@chrjorgensen
Copy link
Collaborator

@worksofliam Since copy members can be specified in different ways, it's probably a good idea to check the
/COPY documentation for how unspecified elements are handled.

IMHO Especially the following are important details:

  • The default sourcefile searched in the /QSYS.LIB file system - QRPGLESRC
  • When the library list are searched
  • default suffixes for IFS include files
  • Maybe also that the IFS is also searched when no member in /QSYS.LIB is found

@worksofliam
Copy link
Contributor Author

@chrjorgensen The specifics of those rules will be handled in the right language server. The rules you mentioned are specific to RPGLE, whereas CL and COBOL have different rules. The way I implemented these APIs will allow each language server to be flexible and implement the rules separately, but still rely on the same resolver

@worksofliam
Copy link
Contributor Author

@chrjorgensen Tried to use your suggestion, but it is not working as expected. Currently, find only returns the path if the file actually exists, and this suggestion returns the string nonetheless.

for f in /QSYS.LIB/QGPL.LIB/H.FILE/MATH.MBR,/QSYS.LIB/QSYSINC.LIB/MIH.FILE/MATH.MBR,/QSYS.LIB/QSYSINC.LIB/H.FILE/MATH.MBR; do echo $f; done

@chrjorgensen
Copy link
Collaborator

@worksofliam It returns the string nonetheless because you have not included the if condition... 😉

This should do it:

for f in ...a.lot.of.files...; do if [ -f $f ]; then echo $f; break; fi; done

Note I changed the exit 0 to a break which is more appropriate for a do...done loop.

@worksofliam worksofliam marked this pull request as ready for review May 4, 2023 16:42
@worksofliam worksofliam requested a review from chrjorgensen May 4, 2023 16:43
@worksofliam worksofliam marked this pull request as draft May 4, 2023 16:43
@worksofliam
Copy link
Contributor Author

@chrjorgensen Only just saw your comment.. let me try with your new string!

@worksofliam worksofliam marked this pull request as ready for review May 4, 2023 18:47
@worksofliam
Copy link
Contributor Author

@chrjorgensen That is awesome! It will likely perform a lot better too! Thank you so much.

It is now ready for review.

Copy link
Collaborator

@chrjorgensen chrjorgensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@worksofliam I have tested your PR by running the test suite - not using the resolve methods in real life. I just made a little comment, which you may address or not...

When your have considered this, I will approve and merge.

});

if (result.code === 0) {
const [firstMost] = result.stdout.split(`,`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you have a break in your for loop, you don't need to retrieve the "firstmost" - there will be only one...

});

if (result.code === 0 && result.stdout) {
const [firstMost] = result.stdout.split(`\n`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here...

@worksofliam worksofliam self-assigned this May 8, 2023
@worksofliam worksofliam requested a review from chrjorgensen May 8, 2023 14:17
Copy link
Contributor Author

@worksofliam worksofliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your suggestion @chrjorgensen! I made the fix. Please review whenever you're ready.

@worksofliam worksofliam removed their assignment May 8, 2023
@worksofliam
Copy link
Contributor Author

@chrjorgensen Sorry to bug you on this. Can I get one more review?

Copy link
Collaborator

@chrjorgensen chrjorgensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@worksofliam LGTM - approved...

@angelorpa
Copy link
Contributor

seems a bit late to ask, but here i go: this functions must necessarily be implemented using the /usr/bin/find command or coud be done with SQL? maybe using the QSYS2.SYSPARTITIONSTAT for member resolver and QSYS2.IFS_OBJECT_STATISTICS for the streamfile resolver ?

@chrjorgensen
Copy link
Collaborator

@angelorpa Why do you think it is a requirement to use /usr/bin/find?

The find command is used to search for files / directories in a directory and all subdirectories - but that it not what these functions are doing: They check for a member or streamfile in a list of source files / directories. And they only return the first member / streamfile found. Like the compilers do...

find is useful when you search for something in a directory tree - and I use it regularly.
But it is not suited for this use case. Here it is much faster to let the shell loop through the list and check for the member / file. find could potentially take a long time in a big directory tree and "choke" the resolve function...

3 similar comments
@chrjorgensen
Copy link
Collaborator

@angelorpa Why do you think it is a requirement to use /usr/bin/find?

The find command is used to search for files / directories in a directory and all subdirectories - but that it not what these functions are doing: They check for a member or streamfile in a list of source files / directories. And they only return the first member / streamfile found. Like the compilers do...

find is useful when you search for something in a directory tree - and I use it regularly.
But it is not suited for this use case. Here it is much faster to let the shell loop through the list and check for the member / file. find could potentially take a long time in a big directory tree and "choke" the resolve function...

@chrjorgensen
Copy link
Collaborator

@angelorpa Why do you think it is a requirement to use /usr/bin/find?

The find command is used to search for files / directories in a directory and all subdirectories - but that it not what these functions are doing: They check for a member or streamfile in a list of source files / directories. And they only return the first member / streamfile found. Like the compilers do...

find is useful when you search for something in a directory tree - and I use it regularly.
But it is not suited for this use case. Here it is much faster to let the shell loop through the list and check for the member / file. find could potentially take a long time in a big directory tree and "choke" the resolve function...

@chrjorgensen
Copy link
Collaborator

@angelorpa Why do you think it is a requirement to use /usr/bin/find?

The find command is used to search for files / directories in a directory and all subdirectories - but that it not what these functions are doing: They check for a member or streamfile in a list of source files / directories. And they only return the first member / streamfile found. Like the compilers do...

find is useful when you search for something in a directory tree - and I use it regularly.
But it is not suited for this use case. Here it is much faster to let the shell loop through the list and check for the member / file. find could potentially take a long time in a big directory tree and "choke" the resolve function...

@angelorpa
Copy link
Contributor

@angelorpa Why do you think it is a requirement to use /usr/bin/find?

The find command is used to search for files / directories in a directory and all subdirectories - but that it not what these functions are doing: They check for a member or streamfile in a list of source files / directories. And they only return the first member / streamfile found. Like the compilers do...

find is useful when you search for something in a directory tree - and I use it regularly. But it is not suited for this use case. Here it is much faster to let the shell loop through the list and check for the member / file. find could potentially take a long time in a big directory tree and "choke" the resolve function...

@chrjorgensen I think you misunderstood my question or may be i formulated in a wrong way. I understood what this functions have to do, but i want to know if is possible implement this functionality using SQL instead of using the find command. I only was suggesting another way to do it. Tables QSYS2.IFS_OBJECT_STATISTICS and QSYS2.SYSPARTITIONSTAT could be used to search for a streamfile or a member, may be using SQL could be faster, easy to understand and more flexible.

@chrjorgensen
Copy link
Collaborator

@angelorpa It sure is possible to create a search function using the SQL functions you mention - but that would only cover members, not streamfiles (unless you add the QSYS2.IFS_OBJECT_STATISTICS SQL function and then it get's tricky). Also running SQL has a cost when entering the SQL CLI, which runs in a separate job. SQL is great for retrieving information about something, but we just want to know the existence of a member or streamfile, not all its attributes.

Instead of SQL we went for shell scripting, which is widely used in the industry, especially in Linux, and is quick to check for files (does not start a new job for this). We use the for loop and if command, and you can google it easily searching for bash for loop and bash if test. So we actually never leave the shell program (which using SQL or find would do) and just let it do the lookups...

@angelorpa
Copy link
Contributor

@angelorpa It sure is possible to create a search function using the SQL functions you mention - but that would only cover members, not streamfiles (unless you add the QSYS2.IFS_OBJECT_STATISTICS SQL function and then it get's tricky). Also running SQL has a cost when entering the SQL CLI, which runs in a separate job. SQL is great for retrieving information about something, but we just want to know the existence of a member or streamfile, not all its attributes.

Instead of SQL we went for shell scripting, which is widely used in the industry, especially in Linux, and is quick to check for files (does not start a new job for this). We use the for loop and if command, and you can google it easily searching for bash for loop and bash if test. So we actually never leave the shell program (which using SQL or find would do) and just let it do the lookups...

nice, thanks for the feedback.

@worksofliam worksofliam merged commit e2be66a into master May 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API to do member/IFS resolves
4 participants