This commit is contained in:
ge
2025-12-09 11:46:57 +03:00
commit d51a419552
8 changed files with 179 additions and 0 deletions

8
.editorconfig Normal file
View File

@@ -0,0 +1,8 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.v]
indent_style = tab

8
.gitattributes vendored Normal file
View File

@@ -0,0 +1,8 @@
* text=auto eol=lf
*.bat eol=crlf
*.v linguist-language=V
*.vv linguist-language=V
*.vsh linguist-language=V
v.mod linguist-language=V
.vdocignore linguist-language=ignore

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Binaries for programs and plugins
main
os_release
*.exe
*.exe~
*.so
*.dylib
*.dll
# Ignore binary output folders
bin/
# Ignore common editor/system specific metadata
.DS_Store
.idea/
.vscode/
*.iml
# ENV
.env
# vweb and database
*.db
*.js

20
README.md Normal file
View File

@@ -0,0 +1,20 @@
# Freedesktop OS Release
`os_release` module implements the os-release, initrd-release and extension-release
file parser per Freedesktop standard. Those files are intended for operating system
identification. Learn more at
[os-release(5)](https://www.freedesktop.org/software/systemd/man/latest/os-release.html)
manual page.
Usage example:
```v
import os_release
fn main() {
release_data := os_release.os_release()
os_name := release_data['PRETTY_NAME'] or { 'Linux' }
os_version := release_data['VERSION_ID'] or { '0' }
println('OS: ${os_name} ${os_version}')
}
```

22
UNLICENSE Normal file
View File

@@ -0,0 +1,22 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and
successors. We intend this dedication to be an overt act of relinquishment in
perpetuity of all present and future rights to this software under copyright
law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

69
os_release.v Normal file
View File

@@ -0,0 +1,69 @@
module os_release
import os
import strings
// options contains list of default os-release, initrd-release, extension-release options.
pub const options = ['NAME', 'ID', 'ID_LIKE', 'PRETTY_NAME', 'CPE_NAME', 'VARIANT', 'VARIANT_ID',
'VERSION', 'VERSION_ID', 'VERSION_CODENAME', 'BUILD_ID', 'IMAGE_ID', 'IMAGE_VERSION',
'RELEASE_TYPE', 'HOME_URL', 'DOCUMENTATION_URL', 'SUPPORT_URL', 'BUG_REPORT_URL',
'PRIVACY_POLICY_URL', 'SUPPORT_END', 'LOGO', 'ANSI_COLOR', 'VENDOR_NAME', 'VENDOR_URL',
'EXPERIMENT', 'EXPERIMENT_URL', 'DEFAULT_HOSTNAME', 'ARCHITECTURE', 'SYSEXT_LEVEL',
'CONFEXT_LEVEL', 'SYSEXT_SCOPE', 'CONFEXT_SCOPE', 'PORTABLE_PREFIXES']!
// os_release reads `/etc/os-release` and `/usr/lib/os-release` files and returns parsed
// os-release data. Empty map will be returned if files does not exits or reading issues
// caused. The resulting map will contain only options that is present in actual os-release
// file.
pub fn os_release() map[string]string {
mut ret := map[string]string{}
for file in ['/etc/os-release', '/usr/lib/os-release'] {
ret = parse_file(file) or { continue }
}
return ret
}
// parse_file reads the `file` and returns map of os-release key-value pairs.
pub fn parse_file(file string) !map[string]string {
return parse(os.read_file(file)!)
}
// parse parses the `content` string and returns map of os-release key-value pairs.
// Example:
// ```
// assert os_release.parse('PRETTY_NAME="Debian GNU/Linux 13 (trixie)"') == {'PRETTY_NAME': 'Debian GNU/Linux 13 (trixie)'}
// ```
pub fn parse(content string) map[string]string {
mut ret := map[string]string{}
for raw_line in content.split_into_lines() {
line := raw_line.trim_space()
if line.is_blank() || line.starts_with('#') {
continue
}
key, value := line.split_once('=') or { continue }
if key == '' {
continue
}
ret = {
...ret
key: unescape(value)
}
}
return ret
}
fn unescape(s string) string {
mut ret := strings.new_builder(128)
for i := 0; i < s.len; i++ {
if (i == 0 || i == s.len - 1) && s[i] in [`"`, `'`] {
continue // trim leading and trailing quotes
}
if s[i] == `\\` && i + 1 < s.len {
ret.write_byte(s[i + 1])
i++
} else {
ret.write_byte(s[i])
}
}
return ret.str()
}

21
os_release_test.v Normal file
View File

@@ -0,0 +1,21 @@
module os_release
fn test_os_release() {
$if !windows {
r := os_release()
dump(r)
assert r['NAME'] != ''
}
}
fn test_os_release_parser() {
content := r'ID=linux
NAME="Linux"
PRETTY_NAME="Linux"
VARIANT="\$erver\ Edition"'.trim_indent()
result := parse(content)
assert result['ID'] == 'linux'
assert result['NAME'] == 'Linux'
assert result['PRETTY_NAME'] == 'Linux'
assert result['VARIANT'] == r'$erver Edition'
}

7
v.mod Normal file
View File

@@ -0,0 +1,7 @@
Module {
name: 'os_release'
description: 'Freedesktop OS Release Parser'
version: '1.0.0'
license: 'Unlicense'
dependencies: []
}