Different behaviour when producing annotations with Erlang Typer - erlang

I am using the typer_core module of Dialyzer to automatically infer typespecs. However, I am obtaining different behaviour based on whether the files specified are prepended with the . character or not. The behaviour described below only affects files located in the directory where the typer command is run; files in child directories are processed as expected by Typer.
Consider the module test.erl:
-module(test).
is_a_ok(a) -> ok.
The behaviour below is produced when evaluating the following expressions on the REPL:
% Prepending with the '.' character.
% Creates the file ./typer_ann/test.ann.erl, but is NOT annotated.
typer_core:run(#{mode => annotate, files => ["./test.erl"]}).
Processing file: "./test.erl"
Saved as: "./typer_ann/test.ann.erl"
% Does NOT annotate the file ./test.erl.
typer_core:run(#{mode => annotate_in_place, files => ["./test.erl"]}).
Processing file: "./test.erl"
Saved as: "./test.erl"
% Without the '.' character.
% Creates the file ./typer_ann/test.ann.erl, and is annotated.
typer_core:run(#{mode => annotate, files => ["test.erl"]}).
Processing file: "test.erl"
Saved as: "./typer_ann/test.ann.erl"
% Annotates the file ./test.erl.
typer_core:run(#{mode => annotate_in_place, files => ["test.erl"]}).
Processing file: "test.erl"
Saved as: "test.erl"
Using . in conjunction with the files_r key (equivalent to the -r command line switch) processes directories recursively. I observed the same behaviour described above when attempting to annotate files with the files_r key, specifying . as the starting directory:
% Does NOT annotate any of the files in the current directory.
typer_core:run(#{mode => annotate_in_place, files_r => ["."]}).
Processing file: "./test.erl"
Saved as: "./test.erl"
This can be reproduced using Typer on the command line:
# Does NOT annotate the file ./test.erl.
$ typer --annotate-in-place ./test.erl
Processing file: "./test.erl"
Saved as: "./test.erl"
# Does NOT annotate any of the files in the current directory.
$ typer --annotate-in-place -r .
Processing file: "./test.erl"
Saved as: "./test.erl"
Note that, however, *.erl files in child directories do get annotated in the first and last examples, i.e. using typer_core:run(#{mode => annotate_in_place, files_r => ["."]}) and typer --annotate-in-place -r . The following examples also work:
# Annotates the file ./test.erl (no . in front of the file name).
$ typer --annotate-in-place test.erl
Processing file: "test.erl"
Saved as: "test.erl"
# Annotates the file test.erl (. in front of the directory, one directory up).
$ typer --annotate-in-place ./typer_test/test.erl
Processing file: "./typer_test/test.erl"
Saved as: "./typer_test/test.erl"
I might be missing something and would appreciate any suggestions regarding this behaviour. I am using OTP 25.0.4.

Related

Unix. Parse file with full paths to SHA256 checksums files. Run command in each path/file

I have a file file.txt with filenames ending with *.sha256, including the full paths of each file. This is a toy example:
file.txt:
/path/a/9b/x3.sha256
/path/7c/7j/y2.vcf.gz.sha256
/path/e/g/7z.sha256
Each line has a different path/file. The *.sha256 files have checksums.
I want to run the command "sha256sum -c" on each of these *.sha256 files and write the output to an output_file.txt. However, this command only accepts the name of the .sha256 file, not the name including its full path. I have tried the following:
while read in; do
sha256sum -c "$in" >> output_file.txt
done < file.txt
but I get:
"sha256sum: WARNING: 1 listed file could not be read"
which is due to the path included in the command.
Any suggestion is welcome
#!/bin/bash
while read in
do
thedir=$(dirname "$in")
thefile=$(basename "$in")
cd "$thedir"
sha256sum -c "$thefile" >>output_file.txt
done < file.txt
Modify your code to extract the directory and file parts of your in variable.

I don't want to ignore a file with no extension

I have a credentials file with no extension.
I would like to add this file to the docker to be available in the app directory.
Right now I have a file added in the root of the application but after building the image the file is missing
My dockerignore
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
Try +([^.])
https://unix.stackexchange.com/a/87649
The bash extended glob +([^.]) will match files without any . in their name. It requires that you have not unset shopt extglob (on modern bash installations, it should be set by default). The pattern means:
any number (but at least one) of characters other than .

Dockerignore: allow to add only specific extension like *.json from any subfolder

I have a .dockerignore file and I'm trying to allow Docker to upload only *.json files but from any of subfolders.
For example, for the next files structure:
public/readme.md
public/subfolder/a.json
public/subfolder/b.json
public/other/c.json
public/other/file.txt
I'm expecting to see only json files in the image:
public/subfolder/a.json
public/subfolder/b.json
public/other/c.json
Of course they must be located in the same directories as in original source.
I tried several ways but didn't succeed.
UP: I don't know how many subfolders will be created in the public/ directory and how deep will be the directories structure.
I think you can achieve what you want by relying on one such .dockerignore:
public/*
!public/subfolder
public/subfolder/*
!public/other
public/other/*
!**/*.json
The tricky thing is that the first line of this file is public/* but not public nor * (otherwise the !... subsequent lines won't work).
Note also that you may want to automate the generation of one such .dockerignore, to cope with possible tree structure changes.
For example:
gen-dockerignore.sh
#!/usr/bin/env bash
{ echo '*' ; # header of the .dockerignore - to be changed if need be
find public -type d -exec echo -en "!{}\n{}/*\n" \; ;
echo '!**/*.json' ; } > .dockerignore
$ ./gen-dockerignore.sh would output the following file:
.dockerignore
*
!public
public/*
!public/other
public/other/*
!public/subfolder
public/subfolder/*
!**/*.json

Why Erlang sasl application doesn't save my log files correctly?

I booted the Erlang shell with sasl started and with the following configuration file, but it doesn't create an error log on disk:
%% rotating log and minimal tty
[{sasl, [
{sasl_error_logger, false},
%% define the parameters of the rotating log
%% the log file directory
{error_logger_mf_dir,"ErrorLogger/erLog"},
%% # bytes per logfile
{error_logger_mf_maxbytes,10485760}, % 10 MB
%% maximum number of logfiles
{error_logger_mf_maxfiles, 10}
]}].
However if I place "." as the directory value, it creates unnamed logs on disk: {error_logger_mf_dir,"."}
You must provide absolute or relative address for error_logger_mf_dir config.
Absolute:
%% the log file absolute directory
{error_logger_mf_dir,"/path/to/ErrorLogger/erLog"},
Relative:
%% the log file based on current directory
{error_logger_mf_dir,"./ErrorLogger/erLog"},
%% Also it must work
{error_logger_mf_dir,"ErrorLogger/erLog"},
Note: Make sure that your Erlang application has write access to ErrorLogger/erLog directory. If so sasl will create there one file called index, and report files 1, 2, 3 and so on which should be browsed by the Report Browser (rb) tool.

How do I run a beam file compiled by Elixir or Erlang?

I have installed Erlang/OTP and Elixir, and compiled the HelloWorld program into a BEAM using the command:
elixirc test.ex
Which produced a file named Elixir.Hello.beam
How do I run this file?
Short answer: no way to know for sure without also knowing the contents of your source file :)
There are a few ways to run Elixir code. This answer will be an overview of various workflows that can be used with Elixir.
When you are just getting started and want to try things out, launching iex and evaluating expressions one at a time is the way to go.
iex(5)> Enum.reverse [1,2,3,4]
[4, 3, 2, 1]
You can also get help on Elixir modules and functions in iex. Most of the functions have examples in their docs.
iex(6)> h Enum.reverse
def reverse(collection)
Reverses the collection.
[...]
When you want to put some code into a file to reuse it later, the recommended (and de facto standard) way is to create a mix project and start adding modules to it. But perhaps, you would like to know what's going on under the covers before relying on mix to perform common tasks like compiling code, starting applications, and so on. Let me explain that.
The simplest way to put some expressions into a file and run it would be to use the elixir command.
x = :math.sqrt(1234)
IO.puts "Your square root is #{x}"
Put the above fragment of code into a file named simple.exs and run it with elixir simple.exs. The .exs extension is just a convention to indicate that the file is meant to be evaluated (and that is what we did).
This works up until the point you want to start building a project. Then you will need to organize your code into modules. Each module is a collection of functions. It is also the minimal compilation unit: each module is compiled into a .beam file. Usually people have one module per source file, but it is also fine to define more than one. Regardless of the number of modules in a single source file, each module will end up in its own .beam file when compiled.
defmodule M do
def hi(name) do
IO.puts "Hello, #{name}"
end
end
We have defined a module with a single function. Save it to a file named mymod.ex. We can use it in multiple ways:
launch iex and evaluate the code in the spawned shell session:
$ iex mymod.ex
iex> M.hi "Alex"
Hello, Alex
:ok
evaluate it before running some other code. For example, to evaluate a single expression on the command line, use elixir -e <expr>. You can "require" (basically, evaluate and load) one or more files before it:
$ elixir -r mymod.ex -e 'M.hi "Alex"'
Hello, Alex
compile it and let the code loading facility of the VM find it
$ elixirc mymod.ex
$ iex
iex> M.hi "Alex"
Hello, Alex
:ok
In that last example we compiled the module which produced a file named Elixir.M.beam in the current directory. When you then run iex in the same directory, the module will be loaded the first time a function from it is called. You could also use other ways to evaluate code, like elixir -e 'M.hi "..."'. As long as the .beam file can be found by the code loader, the module will be loaded and the appropriate function in it will be executed.
However, this was all about trying to play with some code examples. When you are ready to build a project in Elixir, you will need to use mix. The workflow with mix is more or less as follows:
$ mix new myproj
* creating README.md
* creating .gitignore
* creating mix.exs
[...]
$ cd myproj
# 'mix new' has generated a dummy test for you
# see test/myproj_test.exs
$ mix test
Add new modules in the lib/ directory. It is customary to prefix all module names with your project name. So if you take the M module we defined above and put it into the file lib/m.ex, it'll look like this:
defmodule Myproj.M do
def hi(name) do
IO.puts "Hello, #{name}"
end
end
Now you can start a shell with the Mix project loaded in it.
$ iex -S mix
Running the above will compile all your source file and will put them under the _build directory. Mix will also set up the code path for you so that the code loader can locate .beam files in that directory.
Evaluating expressions in the context of a mix project looks like this:
$ mix run -e 'Myproj.M.hi "..."'
Again, no need to compile anything. Most mix tasks will recompile any changed files, so you can safely assume that any modules you have defined are available when you call functions from them.
Run mix help to see all available tasks and mix help <task> to get a detailed description of a particular task.
To specifically address the question:
$ elixirc test.ex
will produce a file named Elixir.Hello.beam, if the file defines a Hello module.
If you run elixir or iex from the directory containing this file, the module will be available. So:
$ elixir -e Hello.some_function
or
$ iex
iex(1)> Hello.some_function
Assume that I write an Elixir program like this:
defmodule PascalTriangle do
defp next_row(m), do: for(x <- (-1..Map.size(m)-1), do: { (x+1), Map.get(m, x, 0) + Map.get(m, x+1, 0) } ) |> Map.new
def draw(1), do: (IO.puts(1); %{ 0 => 1})
def draw(n) do
(new_map = draw(n - 1) |> next_row ) |> Map.values |> Enum.join(" ") |> IO.puts
new_map
end
end
The module PascalTriangle can be used like this: PascalTriangle.draw(8)
When you use elixirc to compile the ex file, it will create a file called Elixir.PascalTriangle.beam.
From command line, you can execute the beam file like this:
elixir -e "PascalTriangle.draw(8)"
You can see the output similar to the photo:

Resources