using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Octokit.Internal;
namespace Octokit
{
///
/// Searching Code/Files
/// http://developer.github.com/v3/search/#search-code
///
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class SearchCodeRequest : BaseSearchRequest
{
///
/// Initializes a new instance of the class.
///
/// The search term.
public SearchCodeRequest(string term) : base(term)
{
Repos = new RepositoryCollection();
}
///
/// Initializes a new instance of the class.
///
/// The term.
/// The owner.
/// The name.
public SearchCodeRequest(string term, string owner, string name)
: this(term)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
Repos.Add(owner, name);
}
///
/// Optional Sort field. Can only be indexed, which indicates how recently
/// a file has been indexed by the GitHub search infrastructure.
/// If not provided, results are sorted by best match.
///
///
/// http://developer.github.com/v3/search/#search-code
///
public CodeSearchSort? SortField { get; set; }
public override string Sort
{
get { return SortField.ToParameter(); }
}
///
/// Qualifies which fields are searched. With this qualifier you can restrict
/// the search to just the file contents, the file path, or both.
///
///
/// https://help.github.com/articles/searching-code#search-in
///
private IEnumerable _inQualifier;
public IEnumerable In
{
get { return _inQualifier; }
set
{
if (value != null && value.Any())
{
_inQualifier = value.Distinct().ToList();
}
}
}
///
/// Searches code based on the language it’s written in.
///
///
/// https://help.github.com/articles/searching-code#language
///
public Language? Language { get; set; }
///
/// Specifies that code from forked repositories should be searched.
/// Repository forks will not be searchable unless the fork has more
/// stars than the parent repository.
///
///
/// https://help.github.com/articles/searching-code#forks
///
public bool? Forks { get; set; }
///
/// Finds files that match a certain size (in bytes).
///
///
/// https://help.github.com/articles/searching-code#size
///
public Range Size { get; set; }
///
/// Specifies the path that the resulting file must be at.
///
///
/// https://help.github.com/articles/searching-code#path
///
public string Path { get; set; }
///
/// Matches files with a certain extension.
///
///
/// https://help.github.com/articles/searching-code#extension
///
public string Extension { get; set; }
///
/// Matches specific file names
///
///
/// https://help.github.com/articles/searching-code/#search-by-filename
///
public string FileName { get; set; }
///
/// Limits searches to a specific user.
///
///
/// https://help.github.com/articles/searching-code#users-organizations-and-repositories
///
public string User { get; set; }
///
/// Limits searches to a specific repository.
///
///
/// https://help.github.com/articles/searching-code#users-organizations-and-repositories
///
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public RepositoryCollection Repos { get; set; }
[SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower")]
public override IReadOnlyList MergedQualifiers()
{
var parameters = new List();
if (In != null)
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "in:{0}",
string.Join(",", In.Select(i => i.ToParameter()))));
}
if (Language != null)
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:{0}", Language.ToParameter()));
}
if (Forks != null)
{
// API is expecting 'true', bool.ToString() returns 'True', if there is a better way,
// please, oh please let me know...
parameters.Add(string.Format(CultureInfo.InvariantCulture, "fork:{0}", Forks.Value.ToString().ToLower()));
}
if (Size != null)
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "size:{0}", Size));
}
if (Path.IsNotBlank())
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "path:{0}", Path));
}
if (Extension.IsNotBlank())
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "extension:{0}", Extension));
}
if (FileName.IsNotBlank())
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "filename:{0}", FileName));
}
if (User.IsNotBlank())
{
parameters.Add(string.Format(CultureInfo.InvariantCulture, "user:{0}", User));
}
if (Repos.Any())
{
var invalidFormatRepos = Repos.Where(x => !x.IsNameWithOwnerFormat());
if (invalidFormatRepos.Any())
{
throw new RepositoryFormatException(invalidFormatRepos);
}
parameters.Add(
string.Join("+", Repos.Select(x => "repo:" + x)));
}
return new ReadOnlyCollection(parameters);
}
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Term: {0} Sort: {1}", Term, Sort);
}
}
}
public enum CodeSearchSort
{
[Parameter(Value = "indexed")]
Indexed
}
public enum CodeInQualifier
{
[Parameter(Value = "file")]
File,
[Parameter(Value = "path")]
Path
}
}