Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/logging.rs @ 53040:cdd7bf612c7b stable tip
bundle-spec: properly format boolean parameter (issue6960)
This was breaking automatic clone bundle generation. This changeset fixes it and
add a test to catch it in the future.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Mar 2025 02:29:42 +0100 |
parents | 7be39c5110c9 |
children |
rev | line source |
---|---|
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
1 use crate::errors::{HgError, HgResultExt, IoErrorContext, IoResultExt}; |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
2 use crate::vfs::{Vfs, VfsImpl}; |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
3 use std::io::Write; |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
4 use std::path::Path; |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
5 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
6 /// An utility to append to a log file with the given name, and optionally |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
7 /// rotate it after it reaches a certain maximum size. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
8 /// |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
9 /// Rotation works by renaming "example.log" to "example.log.1", after renaming |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
10 /// "example.log.1" to "example.log.2" etc up to the given maximum number of |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
11 /// files. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
12 pub struct LogFile<'a> { |
51906 | 13 vfs: VfsImpl, |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
14 name: &'a str, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
15 max_size: Option<u64>, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
16 max_files: u32, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
17 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
18 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
19 impl<'a> LogFile<'a> { |
51906 | 20 pub fn new(vfs: VfsImpl, name: &'a str) -> Self { |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 Self { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
22 vfs, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
23 name, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
24 max_size: None, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
25 max_files: 0, |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
26 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
27 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
28 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
29 /// Rotate before writing to a log file that was already larger than the |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
30 /// given size, in bytes. `None` disables rotation. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
31 pub fn max_size(mut self, value: Option<u64>) -> Self { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
32 self.max_size = value; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
33 self |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
34 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
35 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
36 /// Keep this many rotated files `{name}.1` up to `{name}.{max}`, in |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
37 /// addition to the original `{name}` file. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
38 pub fn max_files(mut self, value: u32) -> Self { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
39 self.max_files = value; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
40 self |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
41 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
43 /// Append the given `bytes` as-is to the log file, after rotating if |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
44 /// needed. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
45 /// |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
46 /// No trailing newline is added. Make sure to include one in `bytes` if |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
47 /// desired. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
48 pub fn write(&self, bytes: &[u8]) -> Result<(), HgError> { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
49 let path = self.vfs.join(self.name); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
50 let context = || IoErrorContext::WritingFile(path.clone()); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
51 let open = || { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
52 std::fs::OpenOptions::new() |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
53 .create(true) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
54 .append(true) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
55 .open(&path) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
56 .with_context(context) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
57 }; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
58 let mut file = open()?; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
59 if let Some(max_size) = self.max_size { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
60 if file.metadata().with_context(context)?.len() >= max_size { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
61 // For example with `max_files == 5`, the first iteration of |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
62 // this loop has `i == 4` and renames `{name}.4` to `{name}.5`. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
63 // The last iteration renames `{name}.1` to |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
64 // `{name}.2` |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
65 for i in (1..self.max_files).rev() { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
66 self.vfs |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
67 .rename( |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
68 Path::new(&format!("{}.{}", self.name, i)), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
69 Path::new(&format!("{}.{}", self.name, i + 1)), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
70 false, |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
71 ) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
72 .io_not_found_as_none()?; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
73 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
74 // Then rename `{name}` to `{name}.1`. This is the |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
75 // previously-opened `file`. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
76 self.vfs |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
77 .rename( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
78 Path::new(&self.name), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
79 Path::new(&format!("{}.1", self.name)), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
80 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
81 ) |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
82 .io_not_found_as_none()?; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
83 // Finally, create a new `{name}` file and replace our `file` |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
84 // handle. |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
85 file = open()?; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
86 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
87 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
88 file.write_all(bytes).with_context(context)?; |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
89 file.sync_all().with_context(context) |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
90 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
91 } |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
92 |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
93 #[test] |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
94 fn test_rotation() { |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
95 let temp = tempfile::tempdir().unwrap(); |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
96 let vfs = VfsImpl::new(temp.path().to_owned(), false); |
51906 | 97 let logger = LogFile::new(vfs.clone(), "log") |
98 .max_size(Some(3)) | |
99 .max_files(2); | |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
100 logger.write(b"one\n").unwrap(); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
101 logger.write(b"two\n").unwrap(); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
102 logger.write(b"3\n").unwrap(); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
103 logger.write(b"four\n").unwrap(); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
104 logger.write(b"five\n").unwrap(); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
105 assert_eq!(vfs.read("log").unwrap(), b"five\n"); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
106 assert_eq!(vfs.read("log.1").unwrap(), b"3\nfour\n"); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
107 assert_eq!(vfs.read("log.2").unwrap(), b"two\n"); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
108 assert!(vfs.read("log.3").io_not_found_as_none().unwrap().is_none()); |
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
109 } |