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

ossia / score / 31975605394

16 Aug 2026 10:10PM UTC coverage: 20.35%. First build
31975605394

Pull #2211

github

web-flow
Merge 1defa584c into bb5e533af
Pull Request #2211: project: collect, relink, trim and archive a project's files

1182 of 1996 new or added lines in 43 files covered. (59.22%)

43464 of 213584 relevant lines covered (20.35%)

5552.46 hits per line

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

93.67
/src/plugins/score-lib-process/Process/MissingFiles.cpp
1
#include <Process/MissingFiles.hpp>
2
#include <Process/ProjectConsolidation.hpp>
3

4
#include <score/document/DocumentContext.hpp>
5

6
#include <QDirIterator>
7
#include <QFileInfo>
8

9
#include <algorithm>
10

11
namespace Process
12
{
13

14
FileReport scanMissingFiles(const score::DocumentContext& ctx)
10✔
15
{
16
  const auto target = projectTarget(ctx);
10✔
17

18
  auto report = runFileOperation(
20✔
19
      ctx,
10✔
20
      [&](const ExternalFileRef& ref, FileEntry& e) -> QString {
23✔
21
    if(!ref.rewritable || ref.directory || ref.usage == FileUsage::Output)
13✔
22
    {
NEW
23
      e.action = FileAction::Unsupported;
×
NEW
24
      return {};
×
25
    }
26

27
    e.sourcePath = score::locateFilePath(ref.path, target.sourceRoots);
13✔
28
    if(e.sourcePath.isEmpty() || !QFileInfo::exists(e.sourcePath))
13✔
29
    {
30
      e.action = FileAction::Missing;
8✔
31
      return {};
8✔
32
    }
33

34
    e.action = FileAction::Unchanged;
5✔
35
    e.size = QFileInfo{e.sourcePath}.size();
5✔
36
    return {};
5✔
37
      },
13✔
38
      /*dryRun=*/true);
39

40
  report.projectFolder = target.folder;
10✔
41
  return report;
10✔
42
}
10✔
43

44
void FileIndex::scan(const QString& folder, int maxFiles)
7✔
45
{
46
  m_root = folder;
7✔
47
  m_byName.clear();
7✔
48
  m_truncated = false;
7✔
49

50
  if(folder.isEmpty())
7✔
51
    return;
1✔
52

53
  QDirIterator it{
6✔
54
      folder, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable,
6✔
55
      QDirIterator::Subdirectories};
6✔
56

57
  while(it.hasNext())
17✔
58
  {
59
    const QString path = it.next();
12✔
60
    if(m_byName.size() >= maxFiles)
12✔
61
    {
62
      m_truncated = true;
1✔
63
      break;
1✔
64
    }
65
    m_byName.insert(it.fileName().toLower(), path);
11✔
66
  }
12✔
67
}
7✔
68

69
std::vector<QString>
70
FileIndex::candidates(const QString& missingPath, qint64 size) const
8✔
71
{
72
  const QString name = QFileInfo{missingPath}.fileName().toLower();
8✔
73
  if(name.isEmpty())
8✔
NEW
74
    return {};
×
75

76
  std::vector<QString> found;
8✔
77
  for(auto it = m_byName.constFind(name); it != m_byName.constEnd() && it.key() == name;
16✔
78
      ++it)
8✔
79
    found.push_back(it.value());
8✔
80

81
  // Best first: a size match beats a name match, and among equals the file
82
  // closest to the folder the user pointed at is the likelier one.
83
  std::stable_sort(
8✔
84
      found.begin(), found.end(), [&](const QString& a, const QString& b) {
10✔
85
    if(size > 0)
2✔
86
    {
87
      const bool sa = QFileInfo{a}.size() == size;
1✔
88
      const bool sb = QFileInfo{b}.size() == size;
1✔
89
      if(sa != sb)
1✔
90
        return sa;
1✔
NEW
91
    }
×
92
    return a.count('/') < b.count('/');
1✔
93
      });
2✔
94

95
  return found;
8✔
96
}
16✔
97

98
FileReport
99
relinkFiles(const score::DocumentContext& ctx, const QHash<QString, QString>& chosen)
4✔
100
{
101
  const auto target = projectTarget(ctx);
4✔
102

103
  auto report = runFileOperation(
8✔
104
      ctx,
4✔
105
      [&](const ExternalFileRef& ref, FileEntry& e) -> QString {
9✔
106
    const auto it = chosen.constFind(ref.path);
5✔
107
    if(it == chosen.constEnd())
5✔
NEW
108
      return {};
×
109

110
    e.sourcePath = score::locateFilePath(ref.path, target.sourceRoots);
5✔
111
    e.destinationPath = *it;
5✔
112

113
    if(!QFileInfo::exists(e.destinationPath))
5✔
114
    {
115
      e.action = FileAction::Failed;
1✔
116
      e.note = QObject::tr("%1 does not exist").arg(e.destinationPath);
1✔
117
      return {};
1✔
118
    }
119

120
    // Store it relative when possible: a relink is a chance to make the
121
    // document more portable, not just to make it work once.
122
    e.newStoredPath
8✔
123
        = score::relativizeFilePath(e.destinationPath, target.destinationRoots);
8✔
124
    e.size = QFileInfo{e.destinationPath}.size();
4✔
125
    e.action = FileAction::Relinked;
4✔
126

127
    return e.newStoredPath;
4✔
128
      },
5✔
129
      /*dryRun=*/false, FileOperationKind::Relink);
130

131
  report.projectFolder = target.folder;
4✔
132
  return report;
4✔
133
}
4✔
134
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc