Skip to content

Commit 5350e66

Browse files
committed
resolve conflicts
2 parents ef8496d + 932574e commit 5350e66

76 files changed

Lines changed: 2533 additions & 118 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

GNUmakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ ifdef WIN32
101101
$(CC) $(CFLAGS) -std=c99 -municode -w -o v1.exe $(VC)/$(VCFILE) $(LDFLAGS) -lws2_32
102102
v1.exe -no-parallel -o v2.exe $(VFLAGS) cmd/v
103103
v2.exe -o $(VEXE) $(VFLAGS) cmd/v
104-
del v1.exe
105-
del v2.exe
104+
$(RM) v1.exe
105+
$(RM) v2.exe
106106
else
107107
ifdef LEGACY
108108
$(MAKE) -C $(TMPLEGACY)

cmd/tools/vast/vast.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ fn (t Tree) stmt(node ast.Stmt) &Node {
448448
fn (t Tree) import_module(node ast.Import) &Node {
449449
mut obj := new_object()
450450
obj.add_terse('ast_type', t.string_node('Import'))
451+
obj.add_terse('source_name', t.string_node(node.source_name))
451452
obj.add_terse('mod', t.string_node(node.mod))
452453
obj.add_terse('alias', t.string_node(node.alias))
453454
obj.add_terse('syms', t.array_node_import_symbol(node.syms))

examples/xvweb/todo/main.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub fn (app &App) complete_todo(mut ctx Context, id int) vweb.Result {
9595
} or { return ctx.server_error('could not update TODO') }
9696

9797
// redirect client to the home page and tell the browser to sent a GET request
98-
return ctx.redirect('/', .see_other)
98+
return ctx.redirect('/', typ: .see_other)
9999
}
100100

101101
@['/todo/:id/delete'; post]
@@ -122,7 +122,7 @@ pub fn (app &App) delete_todo(mut ctx Context, id int) vweb.Result {
122122
} or { return ctx.server_error('could not delete TODO') }
123123

124124
// redirect client to the home page and tell the browser to sent a GET request
125-
return ctx.redirect('/', .see_other)
125+
return ctx.redirect('/', typ: .see_other)
126126
}
127127

128128
fn main() {

vlib/log/default.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,8 @@ pub fn info(s string) {
5353
pub fn debug(s string) {
5454
default_logger.debug(s)
5555
}
56+
57+
// set_always_flush called with true, will make the log flush after every single .fatal(), .error(), .warn(), .info(), .debug() call.
58+
pub fn set_always_flush(should_flush_on_every_message bool) {
59+
default_logger.set_always_flush(should_flush_on_every_message)
60+
}

vlib/log/file_log_test.v

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,27 @@ fn test_reopen() {
4040

4141
os.rmdir_all(lfolder) or {}
4242
}
43+
44+
fn test_set_always_flush() {
45+
lfolder := os.join_path(os.vtmp_dir(), rand.ulid())
46+
lpath1 := os.join_path(lfolder, 'current.log')
47+
os.mkdir_all(lfolder)!
48+
defer {
49+
os.rmdir_all(lfolder) or {}
50+
}
51+
dump(lfolder)
52+
mut l := log.Log{
53+
level: .info
54+
}
55+
l.set_full_logpath(lpath1)
56+
l.set_always_flush(true)
57+
l.warn('one warning')
58+
l.info('one info message')
59+
l.error('one error')
60+
l.close()
61+
lcontent1 := os.read_file(lpath1)!
62+
assert lcontent1.len > 0
63+
assert lcontent1.contains('one warning')
64+
assert lcontent1.contains('one error')
65+
assert lcontent1.contains('one info message')
66+
}

vlib/log/log.v

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ mut:
3434
time_format TimeFormat
3535
custom_time_format string = 'MMMM Do YY N kk:mm:ss A' // timestamp with custom format
3636
short_tag bool
37+
always_flush bool // flush after every single .fatal(), .error(), .warn(), .info(), .debug() call
3738
pub mut:
3839
output_file_name string // log output to this file
3940
}
@@ -118,13 +119,19 @@ fn (mut l Log) log_file(s string, level Level) {
118119
timestamp := l.time_format(time.now())
119120
e := tag_to_file(level, l.short_tag)
120121
l.ofile.writeln('${timestamp} [${e}] ${s}') or { panic(err) }
122+
if l.always_flush {
123+
l.flush()
124+
}
121125
}
122126

123127
// log_cli writes log line `s` with `level` to stdout.
124128
fn (l &Log) log_cli(s string, level Level) {
125129
timestamp := l.time_format(time.now())
126130
e := tag_to_cli(level, l.short_tag)
127131
println('${timestamp} [${e}] ${s}')
132+
if l.always_flush {
133+
flush_stdout()
134+
}
128135
}
129136

130137
// send_output writes log line `s` with `level` to either the log file or the console
@@ -244,6 +251,12 @@ pub fn (mut l Log) set_time_format(f TimeFormat) {
244251
l.time_format = f
245252
}
246253

254+
// set_always_flush called with true, will make the log flush after every single .fatal(), .error(), .warn(), .info(), .debug() call.
255+
// That can be much slower, if you plan to do lots of frequent calls, but if your program exits early or crashes, your logs will be more complete.
256+
pub fn (mut l Log) set_always_flush(should_flush_every_time bool) {
257+
l.always_flush = should_flush_every_time
258+
}
259+
247260
// get_time_format will get the log time format
248261
pub fn (l Log) get_time_format() TimeFormat {
249262
return l.time_format

vlib/log/logger_interface.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ mut:
1111
debug(s string)
1212
// utility methods:
1313
set_level(level Level)
14+
set_always_flush(should_flush bool)
1415
free()
1516
}

vlib/log/safe_log.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ pub fn (mut x ThreadSafeLog) set_level(level Level) {
3737
x.mu.unlock()
3838
}
3939

40+
// set_always_flush called with true, will make the log flush after every single .fatal(), .error(), .warn(), .info(), .debug() call.
41+
// That can be much slower, if you plan to do lots of frequent calls, but if your program exits early or crashes, your logs will be more complete.
42+
pub fn (mut x ThreadSafeLog) set_always_flush(should_flush bool) {
43+
x.mu.@lock()
44+
x.Log.set_always_flush(should_flush)
45+
x.mu.unlock()
46+
}
47+
4048
// debug logs a debug message
4149
pub fn (mut x ThreadSafeLog) debug(s string) {
4250
x.mu.@lock()

vlib/os/os.c.v

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,18 @@ pub fn truncate(path string, len u64) ! {
153153
C.open(&char(path.str), o_wronly | o_trunc, 0)
154154
}
155155
if fp < 0 {
156-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
156+
return error_posix()
157157
}
158158
defer {
159159
C.close(fp)
160160
}
161161
$if windows {
162162
if C._chsize_s(fp, len) != 0 {
163-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
163+
return error_posix()
164164
}
165165
} $else {
166166
if C.ftruncate(fp, len) != 0 {
167-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
167+
return error_posix()
168168
}
169169
}
170170
}
@@ -263,8 +263,7 @@ pub fn cp(src string, dst string) ! {
263263
w_src := src.replace('/', '\\')
264264
w_dst := dst.replace('/', '\\')
265265
if C.CopyFile(w_src.to_wide(), w_dst.to_wide(), false) == 0 {
266-
result := C.GetLastError()
267-
return error_with_code('failed to copy ${src} to ${dst}', int(result))
266+
return error_win32(msg: 'failed to copy ${src} to ${dst}')
268267
}
269268
} $else {
270269
fp_from := C.open(&char(src.str), C.O_RDONLY, 0)
@@ -320,7 +319,7 @@ pub fn vfopen(path string, mode string) !&C.FILE {
320319
fp = C.fopen(&char(path.str), &char(mode.str))
321320
}
322321
if isnil(fp) {
323-
return error('failed to open file "${path}"')
322+
return error_posix(msg: 'failed to open file "${path}"')
324323
} else {
325324
return fp
326325
}
@@ -515,7 +514,7 @@ pub fn rm(path string) ! {
515514
rc = C.remove(&char(path.str))
516515
}
517516
if rc == -1 {
518-
return error('Failed to remove "${path}": ' + posix_get_error_msg(C.errno))
517+
return error_posix(msg: 'Failed to remove "${path}": ' + posix_get_error_msg(C.errno))
519518
}
520519
// C.unlink(path.cstr())
521520
}
@@ -526,12 +525,14 @@ pub fn rmdir(path string) ! {
526525
rc := C.RemoveDirectory(path.to_wide())
527526
if !rc {
528527
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya - 0 == false, is failure
529-
return error('Failed to remove "${path}": ' + posix_get_error_msg(C.errno))
528+
return error_win32(
529+
msg: 'Failed to remove "${path}": ' + get_error_msg(int(C.GetLastError()))
530+
)
530531
}
531532
} $else {
532533
rc := C.rmdir(&char(path.str))
533534
if rc == -1 {
534-
return error(posix_get_error_msg(C.errno))
535+
return error_posix()
535536
}
536537
}
537538
}
@@ -868,7 +869,7 @@ fn kind_of_existing_path(path string) PathKind {
868869
pub fn chdir(path string) ! {
869870
ret := $if windows { C._wchdir(path.to_wide()) } $else { C.chdir(&char(path.str)) }
870871
if ret == -1 {
871-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
872+
return error_posix()
872873
}
873874
}
874875

@@ -1021,7 +1022,7 @@ pub fn flush() {
10211022
// Octals like `0o600` can be used.
10221023
pub fn chmod(path string, mode int) ! {
10231024
if C.chmod(&char(path.str), mode) != 0 {
1024-
return error_with_code('chmod failed: ' + posix_get_error_msg(C.errno), C.errno)
1025+
return error_posix(msg: 'chmod failed: ' + posix_get_error_msg(C.errno))
10251026
}
10261027
}
10271028

@@ -1031,7 +1032,7 @@ pub fn chown(path string, owner int, group int) ! {
10311032
return error('os.chown() not implemented for Windows')
10321033
} $else {
10331034
if C.chown(&char(path.str), owner, group) != 0 {
1034-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
1035+
return error_posix()
10351036
}
10361037
}
10371038
}
@@ -1053,7 +1054,7 @@ pub fn open_append(path string) !File {
10531054
}
10541055
}
10551056
if isnil(file.cfile) {
1056-
return error('failed to create(append) file "${path}"')
1057+
return error_posix(msg: 'failed to create(append) file "${path}"')
10571058
}
10581059
file.is_opened = true
10591060
return file
@@ -1078,7 +1079,7 @@ pub fn execvp(cmdpath string, cmdargs []string) ! {
10781079
res = C.execvp(&char(cmdpath.str), cargs.data)
10791080
}
10801081
if res == -1 {
1081-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
1082+
return error_posix()
10821083
}
10831084

10841085
// just in case C._execvp returned ... that happens on windows ...
@@ -1112,7 +1113,7 @@ pub fn execve(cmdpath string, cmdargs []string, envs []string) ! {
11121113
// Note: normally execve does not return at all.
11131114
// If it returns, then something went wrong...
11141115
if res == -1 {
1115-
return error_with_code(posix_get_error_msg(C.errno), C.errno)
1116+
return error_posix()
11161117
}
11171118
}
11181119

@@ -1155,3 +1156,36 @@ pub fn last_error() IError {
11551156
return error_with_code(msg, code)
11561157
}
11571158
}
1159+
1160+
// Magic constant because zero is used explicitly at times
1161+
const error_code_not_set = 0x7EFEFEFE
1162+
1163+
@[params]
1164+
struct SystemError {
1165+
msg string
1166+
code int = os.error_code_not_set
1167+
}
1168+
1169+
// Return a POSIX error:
1170+
// Code defaults to last error (from C.errno)
1171+
// Message defaults to POSIX error message for the error code
1172+
@[inline]
1173+
pub fn error_posix(e SystemError) IError {
1174+
code := if e.code == os.error_code_not_set { C.errno } else { e.code }
1175+
message := if e.msg == '' { posix_get_error_msg(code) } else { e.msg }
1176+
return error_with_code(message, code)
1177+
}
1178+
1179+
// Return a Win32 API error:
1180+
// Code defaults to last error (calling C.GetLastError())
1181+
// Message defaults to Win 32 API error message for the error code
1182+
@[inline]
1183+
pub fn error_win32(e SystemError) IError {
1184+
$if windows {
1185+
code := if e.code == os.error_code_not_set { int(C.GetLastError()) } else { e.code }
1186+
message := if e.msg == '' { get_error_msg(code) } else { e.msg }
1187+
return error_with_code(message, code)
1188+
} $else {
1189+
panic('Win32 API not available on this platform.')
1190+
}
1191+
}

vlib/os/os_test.c.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,16 @@ fn test_rmdir_all() {
642642
assert !os.exists('some')
643643
}
644644

645+
fn test_rmdir_not_exist() ! {
646+
dir := 'non_existing_dir'
647+
assert !os.exists(dir)
648+
os.rmdir(dir) or {
649+
// 0x00000002 is both ENOENT in POSIX and ERROR_FILE_NOT_FOUND in Win32 API
650+
assert err.code() == 0x00000002
651+
}
652+
assert !os.exists(dir)
653+
}
654+
645655
fn test_dir() {
646656
$if windows {
647657
assert os.dir('C:\\a\\b\\c') == 'C:\\a\\b'

0 commit comments

Comments
 (0)