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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 47980
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 47980
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 47980
diff changeset
97 let logger = LogFile::new(vfs.clone(), "log")
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 47980
diff changeset
98 .max_size(Some(3))
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 47980
diff changeset
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 }