In the tutorial part II, why can Alloy compose root with parent? - alloy

In the File System Lesson II of the Alloy Tutorial, the following model is described:
// A file system object in the file system
abstract sig FSObject { }
// File system objects must be either directories or files.
sig File, Dir extends FSObject { }
// A File System
sig FileSystem {
root: Dir,
live: set FSObject,
contents: Dir lone-> FSObject,
parent: FSObject ->lone Dir
}{
// root has no parent
no root.parent
// live objects are reachable from the root
live in root.*contents
// parent is the inverse of contents
parent = ~contents
}
Note the no root.parent fact.
The question is: why can Alloy compose root with parent, given that root is a Dir, and Dirs do not have parent relations? (only FileSystems have parent relations)

By defining parent as a field of FileSystem, it gets the type
FileSystem -> FSObject -> Dir
Within the signature fact, there is an implicit this, so root.parent is short for (this.root).(this.parent), which means we're joining the types Dir and FSObject -> Dir. Since FSObject includes Dir, this join is not redundant, and yields a set of type Dir.

Related

In Rust using warp, how do I build filters by configuration?

Starting with a root path:
let root = warp::path::end()
.map(|| "Hello World, at root!");
I would like to construct .or() Filters by configuration:
for path in web_server_config.paths {
root.or(warp::path(path).map(|| "OK")); // or any configurable response
}
I understand now that root is cloned into or() and returns a new instance and a different type that wraps the original type. So I would make root mutable and reassign on each result of or(), but I don't how to type root correctly so that it can accept or() results, and satisfy warp::serve

Need to check if folder exists in workspace in groovy script for jenkins pipeline

I need to check if a specific folder exists, I can not give the full path as some of the folder names will be different each time.
I used the below code -
echo "checking if folder exists"
def files = findFiles glob: '**/*example*'
echo """${files[0].name} ${files[0].path} ${files[0].directory} ${files[0].length} ${files[0].lastModified}"""
example is a folder which is inside -
java-maven-app/src/main/java/com/example
the error, I am getting in pipeline is -
You are getting that error because your files list doesn't have any content. AFAIK findFiles is not capable of finding directories recursively. If you have any known files within the directory you are looking for you may be able to get the full path to that file using findFiles and determine whether your directory exists. But it will not work if the directory is empty. As a better solution, you can use the following script to get a list of all directories recursively.
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
def directories = getDirectories("$WORKSPACE")
echo "$directories"
}
}
}
}
}
#NonCPS
def getDirectories(path) {
def dir = new File(path);
def dirs = [];
dir.traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: -1) { d ->
dirs.add(d)
};
return dirs
}

gulp clean is not working in correct manner

I have directory structure like this.
dist
|--client
|--assets
|--images
|--bower_components
|--server
|--.bower.json
I am trying to clean dist folder, except assets/images folder.
But when i execute this command in dryRun mode, it doesn't remove assets/images file. But after disabling it, it remove all the files and folder.
gulp.task('clean:dist', () => {
del.sync([
`${paths.dist}/!(.git*|.openshift|Procfile)**`,
`${paths.dist}/client/**`,
`!${paths.dist}/client/assets`,
`!${paths.dist}/client/assets/**`], {
//dryRun: true
});
//console.log('dELETE FIELSE ARE: ' + JSON.stringify(value));
});
value of used constant is:
${paths.dist} ='dist';
The offical del documentation states the following:
The glob pattern ** matches all children and the parent.
So this won't work:
del.sync(['public/assets/**', '!public/assets/goat.png']);
You have to explicitly ignore the parent directories too:
del.sync(['public/assets/**', '!public/assets', '!public/assets/goat.png']);
In your case you delete dist/client/**, which includes the dist/client directory itself. If you just ignore dist/client/assets/** the dist/client directory is still deleted.
You need to explicitly ignore the dist/client directory:
gulp.task('clean:dist', () => {
del.sync([
`${paths.dist}/!(.git*|.openshift|Procfile)**`,
`${paths.dist}/client/**`,
`!${paths.dist}/client`,
`!${paths.dist}/client/assets/**`]);
});

how to traverse page cache tree (radix tree) of a file address space in linux kernel

I need to get page-cache statistics of an open file. There is a address_space pointer(f_mapping) in file struct which in turn has the root of the radix tree called page_tree. I need to traverse that tree to get information about all the cached pages for that open file.
There are some functions like radix_tree_for_each_chunk(to iterate over chunks), radix_tree_for_each_chunk_slot (to iterate over slots in one chunk) etc, using these the functionality can be achieved. I am unsure about the proper use (arguments) of the same. It would be helpful if any example is posted.
I figured it out from Linux kernel source code.
struct file *file = filp_open("filename",O_RDONLY,0);
struct address_space *file_addr_space = file->f_mapping;
if(file_addr_space==NULL){
printk("error")
}
struct radix_tree_root file_page_tree_root = file_addr_space->page_tree; //contains all pages in page cache
struct radix_tree_iter iter;
void **slot;
int num_dirty = 0;
radix_tree_for_each_slot(slot,&file_page_tree_root,&iter,0){
struct page *page = radix_tree_deref_slot(slot);
if(page!=NULL){
//printk("information about page");
}
}

Flatten first directory of a FileTree in Gradle

I'm writing a task to extract a tarball into a directory. I don't control this tarball's contents.
The tarball contains a single directory which contains all the files I actually care about. I want to pull everything out of that directory and copy that into my destination.
Example:
/root/subdir
/root/subdir/file1
/root/file2
Desired:
/subdir
/subdir/file1
/file2
Here's what I tried so far, but this seems like a really goofy way of doing it:
copy {
eachFile {
def segments = it.getRelativePath().getSegments() as List
it.setPath(segments.tail().join("/"))
return it
}
from tarTree(resources.gzip('mytarfile.tar.gz'))
into destinationDir
}
For each file, I get the elements of its path, remove the first, join that with /, then set that as the file's path. And this works...sort of. The problem is that this creates the following structure as a result:
/root/subdir
/root/subdir/file1
/root/file2
/subdir
/subdir/file1
/file2
I'm fine with just removing the root directory myself as a final action of the task, but I feel like there should be a much simpler way of doing this.
AFAIK, the only way is to unpack the zip, tar, tgz file :(
There is an open issue here
Please go vote for it!
Until then, the solution isn't very pretty, but not that hard either. In the example below, I am assuming that you want to remove the 'apache-tomcat-XYZ' root-level directory from a 'tomcat' configuration that only includes the apache-tomcat zip file.
def unpackDir = "$buildDir/tmp/apache.tomcat.unpack"
task unpack(type: Copy) {
from configurations.tomcat.collect {
zipTree(it).matching {
// these would be global items I might want to exclude
exclude '**/EMPTY.txt'
exclude '**/examples/**', '**/work/**'
}
}
into unpackDir
}
def mainFiles = copySpec {
from {
// use of a closure here defers evaluation until execution time
// It might not be clear, but this next line "moves down"
// one directory and makes everything work
"${unpackDir}/apache-tomcat-7.0.59"
}
// these excludes are only made up for an example
// you would only use/need these here if you were going to have
// multiple such copySpec's. Otherwise, define everything in the
// global unpack above.
exclude '**/webapps/**'
exclude '**/lib/**'
}
task createBetterPackage(type: Zip) {
baseName 'apache-tomcat'
with mainFiles
}
createBetterPackage.dependsOn(unpack)
Using groovy's syntax, we can use a regex to eliminate the first path segment:
task myCopyTask(type: Copy) {
eachFile {
path -= ~/^.+?\//
}
from tarTree(resources.gzip('mytarfile.tar.gz'))
into destinationDir
includeEmptyDirs = false // ignore empty directories
}

Resources