• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Ortham / libloadorder / 6304723708

25 Sep 2023 08:37PM UTC coverage: 90.445% (+1.7%) from 88.77%
6304723708

push

github

Ortham
Refresh implicitly active plugins when loading current state

Now that implicitly active plugins are pulled from sources that can't be
reasonably assumed to be unchanging, refresh them as part of loading
current state in case they've changed since the last time load order
data was loaded.

Do it as the first thing so that a failure doesn't mess with existing
state.

152 of 152 new or added lines in 4 files covered. (100.0%)

6664 of 7368 relevant lines covered (90.45%)

70436.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.7
/src/load_order/tests.rs
1
/*
2
 * This file is part of libloadorder
3
 *
4
 * Copyright (C) 2017 Oliver Hamlet
5
 *
6
 * libloadorder is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * libloadorder is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with libloadorder. If not, see <http://www.gnu.org/licenses/>.
18
 */
19

20
use std::convert::TryFrom;
21
use std::fmt::Display;
22
use std::fs::{create_dir_all, File, OpenOptions};
23
use std::io::{self, Seek, Write};
24
use std::path::Path;
25

26
use filetime::{set_file_times, FileTime};
27

28
use crate::enums::GameId;
29
use crate::enums::LoadOrderMethod;
30
use crate::game_settings::GameSettings;
31
use crate::load_order::strict_encode;
32
use crate::plugin::Plugin;
33
use crate::tests::copy_to_test_dir;
34

35
use super::mutable::MutableLoadOrder;
36

37
pub fn write_load_order_file<T: AsRef<str> + Display>(
11✔
38
    game_settings: &GameSettings,
11✔
39
    filenames: &[T],
11✔
40
) {
11✔
41
    let mut file = File::create(&game_settings.load_order_file().unwrap()).unwrap();
11✔
42

43
    for filename in filenames {
54✔
44
        writeln!(file, "{}", filename).unwrap();
43✔
45
    }
43✔
46
}
11✔
47

48
pub fn write_active_plugins_file<T: AsRef<str>>(game_settings: &GameSettings, filenames: &[T]) {
37✔
49
    let mut file = File::create(&game_settings.active_plugins_file()).unwrap();
37✔
50

37✔
51
    if game_settings.id() == GameId::Morrowind {
37✔
52
        writeln!(file, "isrealmorrowindini=false").unwrap();
2✔
53
        writeln!(file, "[Game Files]").unwrap();
2✔
54
    }
35✔
55

56
    for filename in filenames {
15,909✔
57
        if game_settings.id() == GameId::Morrowind {
15,872✔
58
            write!(file, "GameFile0=").unwrap();
4✔
59
        } else if game_settings.load_order_method() == LoadOrderMethod::Asterisk {
15,868✔
60
            write!(file, "*").unwrap();
15,821✔
61
        }
15,821✔
62

63
        file.write_all(&strict_encode(filename.as_ref()).unwrap())
15,872✔
64
            .unwrap();
15,872✔
65
        writeln!(file, "").unwrap();
15,872✔
66
    }
67
}
37✔
68

69
pub fn set_timestamps<T: AsRef<str>>(plugins_directory: &Path, filenames: &[T]) {
4✔
70
    for (index, filename) in filenames.iter().enumerate() {
22✔
71
        set_file_times(
22✔
72
            &plugins_directory.join(filename.as_ref()),
22✔
73
            FileTime::zero(),
22✔
74
            FileTime::from_unix_time(i64::try_from(index).unwrap(), 0),
22✔
75
        )
22✔
76
        .unwrap();
22✔
77
    }
22✔
78
}
4✔
79

80
pub fn game_settings_for_test(game_id: GameId, game_path: &Path) -> GameSettings {
205✔
81
    let local_path = game_path.join("local");
205✔
82
    create_dir_all(&local_path).unwrap();
205✔
83
    let my_games_path = game_path.join("my games");
205✔
84
    create_dir_all(&my_games_path).unwrap();
205✔
85

205✔
86
    GameSettings::with_local_and_my_games_paths(game_id, game_path, &local_path, my_games_path)
205✔
87
        .unwrap()
205✔
88
}
205✔
89

90
pub fn mock_game_files(game_id: GameId, game_dir: &Path) -> (GameSettings, Vec<Plugin>) {
197✔
91
    let mut settings = game_settings_for_test(game_id, game_dir);
197✔
92

197✔
93
    copy_to_test_dir("Blank.esm", settings.master_file(), &settings);
197✔
94
    copy_to_test_dir("Blank.esm", "Blank.esm", &settings);
197✔
95
    copy_to_test_dir("Blank.esp", "Blank.esp", &settings);
197✔
96
    copy_to_test_dir("Blank - Different.esp", "Blank - Different.esp", &settings);
197✔
97
    copy_to_test_dir(
197✔
98
        "Blank - Master Dependent.esp",
197✔
99
        "Blank - Master Dependent.esp",
197✔
100
        &settings,
197✔
101
    );
197✔
102
    copy_to_test_dir("Blank.esp", "Blàñk.esp", &settings);
197✔
103

197✔
104
    // Refresh settings to account for newly-created plugin files.
197✔
105
    settings.refresh_implicitly_active_plugins().unwrap();
197✔
106

197✔
107
    let plugins = vec![
197✔
108
        Plugin::new(settings.master_file(), &settings).unwrap(),
197✔
109
        Plugin::with_active("Blank.esp", &settings, true).unwrap(),
197✔
110
        Plugin::new("Blank - Different.esp", &settings).unwrap(),
197✔
111
    ];
197✔
112

197✔
113
    (settings, plugins)
197✔
114
}
197✔
115

116
pub fn to_owned(strs: Vec<&str>) -> Vec<String> {
16✔
117
    strs.into_iter().map(String::from).collect()
16✔
118
}
16✔
119

120
/// Set the master flag to be present or not for the given plugin.
121
/// Only valid for plugins for games other than Morrowind.
122
pub fn set_master_flag(plugin: &Path, present: bool) -> io::Result<()> {
14✔
123
    let mut file = OpenOptions::new().write(true).open(plugin)?;
14✔
124
    file.seek(io::SeekFrom::Start(8))?;
14✔
125

126
    let value = if present { 1 } else { 0 };
14✔
127
    file.write(&[value])?;
14✔
128

129
    Ok(())
14✔
130
}
14✔
131

132
pub fn load_and_insert<T: MutableLoadOrder>(load_order: &mut T, plugin_name: &str) {
510✔
133
    let plugin = Plugin::new(plugin_name, load_order.game_settings()).unwrap();
510✔
134

510✔
135
    match load_order.insert_position(&plugin) {
510✔
136
        Some(position) => {
×
137
            load_order.plugins_mut().insert(position, plugin);
×
138
        }
×
139
        None => {
510✔
140
            load_order.plugins_mut().push(plugin);
510✔
141
        }
510✔
142
    }
143
}
510✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc