Skip to content
This repository has been archived by the owner on Jul 30, 2020. It is now read-only.

Commit

Permalink
Add global .cquery file (#702)
Browse files Browse the repository at this point in the history
* Create `GetHomedirectory()` function

This platform specific function is used to get the user's home
directory. This gives us a base from where to get the global config
file for.

Currently WIP as I'm not sure how to implement this for Windows.

* Find and parse .cquery in home dir if not in project dir

* GetHomeDirectory() -> GetGlobalConfigDirectory()

* Windows specific implementation of `GetGlobalConfigDirectory()`

This is a tentative implementation, I don't have access to windows so
haven't tested it but based on MSDN and StackOverflow this seems to be
the way to go.

* Update *nix implementation of `GetGlobalConfigDirectory()`

As discussed in #648, fallback to $HOME if $XDG_CINFIG_HOME is not
found.

* Use a global .cquery file if none found in the project dir

* Add rational to usage of XDG_CONFIG_HOME

* Create "cquery" directory in .config if it does not exist

* Fix up  on Windows

* Only call `CoTaskMemFree` if `ShGetKnownFolderpath` passes

* Refactor config to optional to improve control flow

* Add comment referencing MSDN blog on getting config dir on Windows

* Implicitly call string constructor using = operator

* Add braces around if-else block

* Fixup some errors introduced when making config optional

* config -> cfg

* Fixup crash when assigning to config

* Load global .cquery config at end of LoadCompilationEntriesfromdirectory

Previously the global .cquery config was being loaded before the
project specific compile_commands.json file. The global .cquery config
is intended as a fallback when there are no other configs, so we don't
want this.

To make it explicit that the global .cquery is being loaded, add a new
parameter to LoadFromDirectorylisting (use_global_config) which, if
true, will load the global .cquery. This parameter defaults to false,
so no changes are required to existing calls.

* Add reference for usage of CoTaskMemFree after SHGetKnownFolderPath

* Load the local .cquery in all cases that it is present
  • Loading branch information
Nick Spain authored and jacobdufault committed Jun 29, 2018
1 parent 8edc3c7 commit 76a7ea6
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ void TraceMe();

optional<std::string> RunExecutable(const std::vector<std::string>& command,
std::string_view input);

optional<std::string> GetGlobalConfigDirectory();
25 changes: 25 additions & 0 deletions src/platform_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,29 @@ optional<std::string> RunExecutable(const std::vector<std::string>& command,
return result;
}

optional<std::string> GetGlobalConfigDirectory() {
char const* xdg_config_home = std::getenv("XDG_CONFIG_HOME");
char const* home = std::getenv("HOME");
optional<std::string> config;

// If it exists use XDG_CONFIG_HOME to comply with the XDG base
// directory spec. Otherwise, use HOME if available.
if (xdg_config_home) {
config = std::string(xdg_config_home);
EnsureEndsInSlash(*config);
*config += "cquery";
if (!FileExists(*config)) {
MakeDirectoryRecursive(AbsolutePath(*config, false));
}
} else if (home) {
*config = home;
}

if (config) {
EnsureEndsInSlash(*config);
}

return config;
}

#endif
28 changes: 28 additions & 0 deletions src/platform_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <fcntl.h>
#include <io.h>
#include <windows.h>
#include <Shlobj.h>
#include <Objbase.h>
#include <Knownfolders.h>

#include <sys/stat.h>
#include <sys/types.h>
Expand All @@ -17,6 +20,8 @@
#include <cassert>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>

namespace {
void EmitError(const std::string& message) {
Expand Down Expand Up @@ -351,4 +356,27 @@ optional<std::string> RunExecutable(const std::vector<std::string>& command,
return output;
}

optional<std::string> GetGlobalConfigDirectory() {
wchar_t *roaming_path = NULL;
optional<std::string> cfg_path = {};
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT,
NULL, &roaming_path))) {
std::wstringstream roaming_stream;
roaming_stream << roaming_path << L"/cquery";

// Convert the roaming path string to a normal string so it
// is analogous with the string returned by the posix version.
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;
cfg_path = converter.to_bytes(roaming_stream.str());

// As per the docs for SHGetKnownFolderPath
// (https://msdn.microsoft.com/en-us/library/bb762188(VS.85).aspx)
// we must free roaming_path using CoTaskMemFree once
// finished with it.
CoTaskMemFree(static_cast<void*>(roaming_path));
}
return cfg_path;
}

#endif
47 changes: 33 additions & 14 deletions src/project.cc
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,9 @@ std::vector<std::string> ReadCompilerArgumentsFromFile(
return args;
}

std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
std::vector<Project::Entry> LoadFromDirectoryListing(
ProjectConfig* config,
bool use_global_config = false) {
std::vector<Project::Entry> result;
config->mode = ProjectMode::DotCquery;

Expand All @@ -476,18 +478,31 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
}
}

GetFilesInFolder(config->project_dir, true /*recursive*/,
true /*add_folder_to_path*/,
[&folder_args, &files](const std::string& path) {
if (SourceFileLanguage(path) != LanguageId::Unknown) {
files.push_back(path);
} else if (GetBaseName(path) == ".cquery") {
LOG_S(INFO) << "Using .cquery arguments from " << path;
folder_args.emplace(GetDirName(path),
ReadCompilerArgumentsFromFile(path));
}
});

GetFilesInFolder(
config->project_dir, true /*recursive*/, true /*add_folder_to_path*/,
[&folder_args, &files](const std::string& path) {
if (SourceFileLanguage(path) != LanguageId::Unknown) {
files.push_back(path);
} else if (GetBaseName(path) == ".cquery") {
LOG_S(INFO) << "Using .cquery arguments from " << path;
folder_args.emplace(GetDirName(path),
ReadCompilerArgumentsFromFile(path));
}
});

if (use_global_config) {
optional<std::string> maybe_cfg = GetGlobalConfigDirectory();
if (folder_args.empty() && maybe_cfg) {
std::string cfg = *maybe_cfg + ".cquery";
if (cfg.size() && FileExists(cfg)) {
LOG_S(INFO) << "Using .cquery arguments from " << cfg;
folder_args.emplace(config->project_dir,
ReadCompilerArgumentsFromFile(cfg));
}
}
}

LOG_IF_S(WARNING, folder_args.empty() && config->extra_flags.empty()
&& !c_cpp_props)
<< "cquery has no clang arguments. Considering adding a "
Expand Down Expand Up @@ -541,8 +556,11 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
ProjectConfig* project,
const std::string& opt_compilation_db_dir) {
// If there is a .cquery file always load using directory listing.
if (FileExists(project->project_dir + ".cquery"))
// The .cquery file can be in the project or home dir but the project
// dir takes precedence.
if (FileExists(project->project_dir + ".cquery")) {
return LoadFromDirectoryListing(project);
}

// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
std::string comp_db_dir(opt_compilation_db_dir);
Expand Down Expand Up @@ -596,6 +614,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
project->project_dir.c_str(), &cx_db_load_error);
}
}

if (!g_config->compilationDatabaseCommand.empty()) {
#if defined(_WIN32)
// TODO
Expand All @@ -608,7 +627,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
if (cx_db_load_error != CXCompilationDatabase_NoError) {
LOG_S(INFO) << "Unable to load compile_commands.json located at \""
<< comp_db_dir << "\"; using directory listing instead.";
return LoadFromDirectoryListing(project);
return LoadFromDirectoryListing(project, true);
}

Timer clang_time;
Expand Down

0 comments on commit 76a7ea6

Please sign in to comment.