Should A Program Create XDG Folders? - specifications

Let's say I'm writing a program, and I want it to follow the XDG Base Directory Specification for where it puts its files (app foo uses $XDG_CONFIG_HOME/foo as the directory for configuration files if XDG_CONFIG_HOME is set and non-blank, or ~/.config/foo, or fails with an error if the home directory can't even be resolved).
Is there a correct/specified behavior for the situation where for example XDG_CONFIG_HOME is set and non-blank, but that directory doesn't exist? Or if there is no such variable, and ~/.config doesn't exist? Is it expected that my program attempt to create it? Or is the non-existance of that directory considered an error on the environment's/system's part, and my program should avoid doing anything about it (just bail with an error)?
Note: I'm not asking if I should create ~/.config/foo - obviously that's a yes; I'm asking if I should create ~/.config itself, if it doesn't exist.
(To be more pedantic: obviously some program should create them - the question is whether it's solely the system's/desktop's/user's job to do so, or if any program should try creating the relevant directories if they don't exist?)
I've tried reading the XDG Base Directory Specification, which says that when attempting to write its files, the program may create the requisite directory, but it's unclear if this is referring to just the application's specific/"personal" sub-directory in the XDG base directories, or if this is meant for the XDG base directories themselves.
P.S. Usually I have a good idea of what tags to use, but here I'm really uncertain: please edit this post or suggest improvements to give it proper tags.

From the XDG Base Directory Specification:
If, when attempting to write a file, the destination directory is
non-existant an attempt should be made to create it with permission
0700. If the destination directory exists already the permissions should not be changed. The application should be prepared to handle
the case where the file could not be written, either because the
directory was non-existant and could not be created, or for any other
reason. In such case it may chose to present an error message to the
user.
I would interpret this so application should try to create the XDG base directory (or any directory required for the destination) and only display an error if it is unable to do so.

I've settled on my own answer after a few years of thinking:
never create non-standard base XDG directories, but
it may be okay to automatically create the standard XDG base directories, and
you should automatically create any of your application's subdirectories within the base directories.
I think it can be good to be automatically helpful, but it is also very important to not worsen a user's mistakes.
If I write XDG_DATA_HOME=~/.locals/hare in my environment variable configuration, I might have wanted that, but it's much more likely that I made a typo of ~/.local/share. So the most helpful, least disruptive, and least wrong thing to do in that case is to report the lack of the requested XDG base directory.
So, if the user has specified a custom XDG base directory, and that base directory does not exist, never try to create it. Don't put your user in a situation where for example next to their standard ~/.config directory they get a ~/.configs or ~/.comfig directory which also contains some of their configurations, until one day they fix the typo and suddenly their programs behave as if they were reset to the defaults. This is a situation where early detection of mistakes is the most helpful thing to do in the long run, so tell the user immediately "this doesn't exist".
But if the user has not asked for a custom base directory, and you're about to use the known, standard location, then it's fine to try to automatically create it, if you ensure you only create it with reasonable ownership, permissions, and so on.
Finally, when the base XDG directory exists, most apps should probably make their own subdirectory inside that, and you definitely should create that app-specific directory, and any other subdirectories inside that one, automatically.

Related

Exclude a file or directory from CODEOWNERS

I have a file structure like so:
foo/file1.c
foo/file2.c
foo/freeforall.c
My foogroup on GitHub needs to review changes to everything in foo except freeforall.c which is a file that anyone can touch without restriction, so it should not automatically add anybody as a reviewer when changes are made to it.
(In reality, whoever modifies freeforall.c just asks someone else on their own team to review their change.)
The Question
How can I do this with GitHub CODEOWNERS? The file looks like this right now:
foo #MyOrg/foogroup
What I Tried
GitHub explicitly says that the ! syntax is not supported, so that won't work:
foo #MyOrg/foogroup
!foo/freeforall.c
And there are too many files in the foo directory to explicitly include them individually. I could move freeforall.c into a different directory, but really I don't want to be having GitHub's CODEOWNER feature dictating how I organize my components. I want freeforall.c to be in the foo directory, that's where it belongs!
I also considered creating an emptygroup to assign that file to, but soon realized that now I'd be requiring that a group with zero members must approve PRs to that file which obviously would cause problems. 😂
foo #MyOrg/foogroup
foo/freeforall.c #MyOrg/emptygroup
The CODEOWNERS file takes the last matching line into account. You can make definitions with empty owners to specify paths/files without an owner.
Consequently, you can use the following lines to have all files in the foo directory owned by #MyOrg/foogroup except foo/freeforall.c:
foo #MyOrg/foogroup
foo/freeforall.c

VSCode how to clear workspaceState data globally?

I have implemented a backup per workspace functionality in my extension using workspaceState. Since the data can be sensitive - I'd like to clear all workspaceStates on extension deactivation/uninstall.
The ExtensionContext provides no ability to clear all extension related data across different workspaces with their workspaceStates.
So I've considered saving data on the ExtensionContext globalState, tagging each entry with a workspace id. Problem is that the workspace namespace doesn't provide a way to uniquely identify the current workspace. I thought about hashing workspace name and path but both of these things are changeable and any change will destroy the pointer to the data. This is exactly why I cant just write files to internal folders. The only other solution I have is to write the backup data directly to the workspace and I'd like to avoid that.
How does VSCode maintain the knowledge of which workspaceState belongs to which workspace? How can I tie data to the workspace but have access from anywhere else in VSCode?
Side note: You should avoid saving sensitive data in general. And if necessary, try to encrypt it.
Anyway:
I don't have the full answers but i was researching something similar (An extension I use crashes due to now invalid settings in the WorkspaceState).
I found the Storage for the Workspace state in this folder (windows):
%appdata%\Code\User\workspaceStorage\
In there, you find a lot of folders with hex-based names. Inside those folders, I always found 2 Files named state.vscdb and state.vscdb.backup.
There usually is a 3rd file called workspace.json which helps you figure out if you are in the correct workspace. (but you'd have to iterate through all the folders - maybe there is a way to figure out the folder name coming from the extension API?)
If you open the state.vscdb-file you find something that looks quite like a serialized object set in my eyes. It does have some Seperator chars of unknown function. But you also find full paths or names in there that clearly origin from different modules of VSC - Including the extensions.
I don't need to worry about the other cached stuff i'm just gonna delete the whole folder to fix my current issue. But I'm pretty sure, one can figure out the way the file is built and edit out your sensitive data if one has to.
The state.vscdb.backup-file looks pretty much like what the name is telling you: they probably just make a copy of the other file every few minutes so you have a fallback position.
To add to the conversation, there are two SQLite state databases:
<user-data-dir>\User\globalStorage\state.vscdb
<user-data-dir>\User\workspaceStorage\<workspace.id>\state.vscdb
Depending on how VS Code was launched you could have a Single Folder Workspace or a Multi-Folder Workspace that is global or local. Globally, the data lives here:
Linux: $HOME/.config/Code/
OS X: $HOME/Library/Application Support/Code/
Windows: %APPDATA%\Code\
Locally, the data will be in the .vscode folder of the current workspace.
In my situation:
I open a new workspace.
Set it up as I want it to start every time.
Makes copies of the two SQLite databases.
Copy over the databases before launching VS Code.
This leads to a clean VS Code state.
To see how workspace.id is generated check this link.

Mapping of URIs to files

I'm trying to understand mapping of URIs to files. Let's take this URI:
modelica://foo.bar/file.png
Is it correct that there are two possible locations for file.png?
It could be either
$MODELICAPATH/foo/file.png if file $MODELICAPATH/foo/bar.mo exists.
Or
$MODELICAPATH/foo/bar/file.png if file $MODELICAPATH/foo/bar/package.mo exists.
Likely Section "13.2.3 External resources" of the Modelica Language Specification helps.
A little modification of your example should help to understand how it works. Using modelica://foo/bar/file.png refers to foo as top-level package/library. The library the path is resolved when it is loaded in the simulation environment. In case you store the library hierarchically (i.e. every package is represented as folder, each model is a file) bar would be a subfolder within the libraries root directory. file.png would be the file name within bar.
This is different if the package is stored as a single file, but as this has several disadvantages I would recommend to go with the hierarchical option.
No need to edit $ModelicaPath$ if the library is loaded.
Usually pictures etc. are put into a Resources folder within the library. This folder can contain additional folders like data, Images, Scripts...

Referencing external files in Eclipse: virtually linked files vs build settings in Project Properties?

There is information on the web as well as here on the topic related to the using external file resources in CDT Eclipse: C/C++ and H files located somewhere else in the files system. All the described methods run along two methods:
creation within the project space the virtual linked files which point to
the locations of the actual files without copying them
adding the location of the external referenced resource in the
Project->Properties->C/C++ general->Paths and Symbols and related
Project->Properties-> C/C++ Build (link folders and includes)
I am not sure if the 1st method is always enough without adding the 2nd, but seems the 2nd builds well without the 1st.
My question is about a comparison of the two. Are those methods intended to be used similarly or each one is preferred in some cases?
Is each method self sufficient without applying the other?
This forum thread
https://www.eclipse.org/forums/index.php/t/1087314/ suggests that for the include files the 1st method might not even be sufficient as the Build Settings should still be updated (2nd method) to include the linked H files...then may be the 1st method is irrelevant?
You would typically use the first method if you want to edit the externally-located files as part of your work on the project, and the second method if they're just dependencies that you use without modifying.
On a technical level, the difference is that with the first method the files will be part of the project model, and so will e.g. show up as candidates in Open Resource, while with the second method they wouldn't. Another difference is that with the first method, the files are indexed independently, while with the second method the files are only indexed by virtue of being included by files in your project (so e.g. .cpp files in those directories typically wouldn't be indexed with the second method at all).
Update: answers to questions from the comment
Is the 1st method sufficient enough in all cases without updating Paths and Symbols Property ?
No, if there are header files located in the linked directory that are included by files in your project using include paths that are not relative to the current directory (so not just #include "foo.h" in the same directory, #include "../foo.h" in a child directory, etc., but #include <bar/foo.h> in some other directory), you still want to specify those include paths in Paths and Symbols.
CDT's indexer does have an "Allow heuristic resolution of includes" option (specified in Preferences -> C/C++ -> Indexer) that may allow you to avoid adding the paths to Paths and Symbols, but note that (1) this affects the indexer only, not the build (which may be fine if you're using your own makefiles for the build), and (2) as it's heuristic, it's not perfect, e.g. if you have headers with the same name in different directories it can get confused. For best accurracy, I recommend unchecking "Allow heuristic resolution of includes", and always specifying include paths explicitly.
Also can the 2nd method be sufficient in itself if referenced files to be used AS IS without modification?
I don't see why not.

What is the closest thing MATLAB has to namespaces?

We have a lot of MATLAB code in my lab. The problem is there's really no way to organize it. Since all the functions have to be in the same folder to be called (or you have to add a bunch of folders to MATLAB's path environment variable), it seems that we're doomed have loads of files in the same folder, all in the global namespace. Is there a better way to organize our files and functions? I really wish there were some sort of module system...
MATLAB has a notion of packages which can be nested and include both classes and functions.
Just make a directory somewhere on your path with a + as the first character, like +mypkg. Then, if there is a class or function in that directory, it may be referred to as mypkg.mything. You can also import from a package using import mypkg.mysubpkg.*.
The one main gotcha about moving a bunch of functions into a package is that functions and classes do not automatically import the package they live in. This means that if you have a bunch of functions in different m-files that call each other, you may have to spend a while dropping imports in or qualifying function calls. Don't forget to put imports into subfunctions that call out as well. More info:
http://www.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html
I don't see the problem with having to add some folder to Matlab's search path. I have modified startup.m so that it recursively looks for directories in my Matlab startup directory, and adds them to the path (it also runs svn update on everything). This way, if I change the directory structure, Matlab is still going to see all the functions the next time I start it.
Otherwise, you can look into object-oriented code, where you store all the methods in a #objectName folder. However, this may lead to a lot of re-writing code that can be avoided by updating the path (there is even a button add with subfolders if you add the folder to the path from the File menu) and doing a bit of moving code.
EDIT
If you would like to organize your code so that some functions are only visible to the functions that call them directly (and if you don't want to re-write in OOP), you put the calling functions in a directory, and within this directory, you create a subdirectory called private. The functions in there will only be visible to the functions in the parent directory. This is very useful if you have to overload some built-in Matlab functions for a subset of your code.
Another way to organize & reuse code is using matlab's object-oriented features. Each Object is customarily in a folder that begins with an "#" and has the file(s) for that class inside. (though the newer syntax does not require this for a class defined in a single file.) Using private folders inside class folders, matlab even supports private class members. Matlab's new class notation is relatively fully-featured, but even the old syntax is useful.
BTW, my startup.m that examines a well-known location that I do my SVN checkouts into, and adds all of the subfolders onto my path automatically.
The package system is probably the best. I use the class system (#ClassName folder), but I actually write objects. If you're not doing that, it's silly just to write a bunch of static methods. One thing that can be helpful is to put all your matlab code into a folder that isn't on the matlab path. Then you can selectively add just the code you need to the path.
So say you have two projects, stored in "c:\matlabcode\foo" and "c"\matlabcode\bar", that both use common code stored in "c:\matlabcode\common," you might have a function "setupPaths.m" like this:
function setupPaths(projectName)
basedir = fullfile('c:', 'matlabcode');
addpath(genpath(fullfile(basedir, projectName)));
switch (projectName)
case {'foo', 'bar'}
addpath(genpath(fullfile(basedir, 'common')));
end
Of course you could extend this. An obvious extension would be to include a text file in each directory saying what other directories should be added to the path to use the functions in that directory.
Another useful thing if you share code is to set up a "user specific/LabMember" directory structure, where you have different lab members save code they are working on. That way you have access to their code if you need it, but don't get clobbered when they write a function with the same name as one of yours.