├── .github └── workflows │ └── main.yml ├── .gitignore ├── Gemfile ├── LICENCE ├── README.md ├── Rakefile ├── TODO.txt ├── bin └── cm ├── docurium.gemspec ├── lib ├── docurium.rb ├── docurium │ ├── cli.rb │ ├── cparser.rb │ ├── css.css │ ├── debug.rb │ ├── docparser.rb │ ├── layout.mustache │ ├── layout.rb │ └── version.rb └── libdetect.rb ├── site ├── css │ └── style.css ├── images │ └── search_icon.png ├── index.html ├── js │ ├── backbone.js │ ├── docurium.js │ ├── json2.js │ └── underscore.js └── shared │ ├── css │ ├── documentation.css │ └── pygments.css │ ├── images │ ├── active-arrow.png │ ├── background-v2.png │ ├── background-white.png │ ├── dropdown_sprites.jpg │ ├── footer_logo.png │ ├── logo.png │ ├── nav-rule.png │ ├── next_step_arrow.gif │ └── qmark.png │ └── js │ └── jquery.js └── test ├── docurium_test.rb ├── fixtures └── git2 │ ├── api.docurium │ ├── blob.h │ ├── callback.h │ ├── cherrypick.h │ ├── commit.h │ ├── common.h │ ├── errors.h │ ├── index.h │ ├── object.h │ ├── odb.h │ ├── odb_backend.h │ ├── oid.h │ ├── refs.h │ ├── repository.h │ ├── revwalk.h │ ├── signature.h │ ├── tag.h │ ├── thread-utils.h │ ├── tree.h │ └── types.h ├── gen_test.rb ├── parser_test.rb └── test_helper.rb /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Docurium 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | ruby: [head, 3.0, 2.7, 2.6] 16 | llvm: ["6.0", 7, 8, 9, 10] 17 | os: [ ubuntu-18.04 ] 18 | include: 19 | - os: macos-latest 20 | ruby: 2.6 21 | llvm: ~ # system 22 | 23 | name: Ruby ${{ matrix.ruby }} / LLVM ${{ matrix.llvm }} on ${{ matrix.os }} 24 | runs-on: ${{ matrix.os }} 25 | continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }} 26 | 27 | steps: 28 | - uses: actions/checkout@v2 29 | - name: Install Linux packages 30 | if: runner.os == 'Linux' 31 | run: | 32 | sudo apt update 33 | sudo apt install -y python-pygments libclang-${{ matrix.llvm }}-dev llvm-${{ matrix.llvm }} clang-${{ matrix.llvm }} 34 | - name: Set up Ruby ${{ matrix.ruby }} 35 | uses: ruby/setup-ruby@v1 36 | with: 37 | ruby-version: ${{ matrix.ruby }} 38 | bundler-cache: true 39 | - name: Run tests 40 | run: | 41 | [ -x /usr/bin/llvm-config-${{ matrix.llvm }} ] && export LLVM_CONFIG=llvm-config-${{ matrix.llvm }} 42 | bundle exec rake 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | site/*.json 3 | *.gem 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.0.0') 4 | platforms :rbx do 5 | gem 'rubysl', '~> 2.2' 6 | end 7 | end 8 | 9 | gemspec 10 | 11 | # vim:ft=ruby 12 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Scott Chacon 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docurium 2 | 3 | Docurium is a lightweight Doxygen replacement. It generates static HTML from the header files of a C project. It is meant to be simple, easy to navigate and git-tag aware. It is only meant to document your public interface, so it only knows about your header files. 4 | 5 | I built it to replace the Doxygen generated documentation for the libgit2 project, so I'm only currently testing it against that. So, it is only known to include support for features and keywords used in that project currently. If you have a C library project you try this on and something is amiss, please file an issue or better yet, a pull request. 6 | 7 | Though Docurium can generate your docs into a subdirectory, it is meant to be served from a webserver, not locally. It uses XMLHttpRequest calls, which cannot be done locally, so you can't just open the index.html file locally and have it work - you need to either run a webserver in the output directory or push it to a website to view it properly. I use Pow (pow.cx) or GitHub Pages. 8 | 9 | # Usage 10 | 11 | Run the `cm` binary and pass it your Docurium config file. 12 | 13 | $ cm doc api.docurium 14 | * generating docs 15 | - processing version v0.1.0 16 | - processing version v0.2.0 17 | - processing version v0.3.0 18 | - processing version v0.8.0 19 | - processing version v0.10.0 20 | - processing version v0.11.0 21 | - processing version v0.12.0 22 | - processing version HEAD 23 | * checking your api 24 | - unmatched params in 25 | git_commit_create 26 | git_config_set_int 27 | git_object_lookup_prefix 28 | - signature changes in 29 | git_index_get 30 | git_repository_path 31 | git_tree_entry_byindex 32 | * writing to branch gh-pages 33 | wrote tree 87f0f3cb1622b9dc3d6d5d39106e863608b3b504 34 | wrote commit 5cee46f4d491e9611abab218604db893b70202f3 35 | updated gh-pages 36 | 37 | Docurium will tell you if you have unmatched @params entries in header docs and if you've changed signatures in functions in HEAD, just to help you know what's happening and if you've written your docs properly. 38 | 39 | The Docurium config file looks like this: 40 | 41 | { 42 | "name": "libgit2", 43 | "github": "libgit2/libgit2", 44 | "input": "include/git2", 45 | "prefix": "git_", 46 | "branch": "gh-pages", 47 | "examples": "examples", 48 | "legacy": { 49 | "input": {"src/git": ["v0.1.0"], 50 | "src/git2": ["v0.2.0", "v0.3.0"]} 51 | } 52 | } 53 | 54 | Docurium will write your docs directly into the specified Git branch. 55 | 56 | # Installing 57 | 58 | $ gem install docurium 59 | 60 | # Contributing 61 | 62 | If you want to fix or change something, please fork on GitHub, push your change to a branch named after your change and send me a pull request. 63 | 64 | # License 65 | 66 | MIT, see LICENCE file 67 | 68 | 69 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | require 'rubygems' 3 | require 'rubygems/package_task' 4 | 5 | task :default => :test 6 | 7 | gemspec = Gem::Specification::load(File.expand_path('../docurium.gemspec', __FILE__)) 8 | Gem::PackageTask.new(gemspec) do |pkg| 9 | end 10 | 11 | Rake::TestTask.new do |t| 12 | t.libs << 'libs' << 'test' 13 | t.pattern = 'test/**/*_test.rb' 14 | end 15 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | TODO 2 | 3 | * broken changelog & index page highlighting 4 | 5 | 6 | * version history for types, too 7 | 8 | * only update certain tags / HEAD, force full update 9 | 10 | * doc other branches (specify in config file) 11 | 12 | * highlight menu item when selected 13 | 14 | -------------------------------------------------------------------------------- /bin/cm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' 3 | 4 | require 'rubygems' 5 | require 'gli' 6 | require 'docurium' 7 | require 'docurium/cli' 8 | 9 | include GLI::App 10 | 11 | version Docurium::Version 12 | 13 | desc 'Generate HTML documentation' 14 | long_desc 'Generate HTML docs from a Docurium config file' 15 | command :doc do |c| 16 | c.flag :for, :desc => "The version to generate", :multiple => true 17 | c.switch [:n, "dry-run"], :desc => "Dry-run" 18 | c.switch [:d, "debug"], :desc => "Enable debug log" 19 | c.flag "debug-file", :desc => "Enable debug output for header", :multiple => true 20 | c.flag "debug-function", :desc => "Show debug output when processing function", :multiple => true 21 | c.flag "debug-type", :desc => "Show debug output when processing type", :multiple => true 22 | c.action do |global_options,options,args| 23 | file = args.first 24 | Docurium::CLI.doc(file, options) 25 | end 26 | end 27 | 28 | desc 'Check documentation for warnings' 29 | long_desc 'Check a project\'s documentation for issues' 30 | command :check do |c| 31 | c.action do |global_options,options,args| 32 | file = args.first 33 | Docurium::CLI.check(file, options) 34 | end 35 | end 36 | 37 | desc 'Generate Docurium config file template' 38 | long_desc 'Generate Docurium config file template' 39 | command :gen do |c| 40 | c.action do |global_options,options,args| 41 | file = args.first || 'api.docurium' 42 | Docurium::CLI.gen(file) 43 | end 44 | end 45 | 46 | 47 | pre { |global,command,options,args| true } 48 | 49 | post { |global,command,options,args| true } 50 | 51 | on_error do |exception| 52 | if !exception.is_a?(SystemExit) 53 | puts exception 54 | puts exception.backtrace 55 | end 56 | end 57 | 58 | exit run(ARGV) 59 | -------------------------------------------------------------------------------- /docurium.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require 'docurium/version' 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "docurium" 7 | s.version = Docurium::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Carlos Martín Nieto", "Scott Chacon"] 10 | s.email = ["cmn@dwim.me", "schacon@gmail.com"] 11 | s.homepage = "https://github.com/libgit2/docurium" 12 | s.summary = "A simpler, prettier Doxygen replacement." 13 | s.description = s.summary 14 | s.license = 'MIT' 15 | 16 | s.add_dependency "version_sorter", "~>2.0" 17 | s.add_dependency "mustache", "~> 1.1" 18 | s.add_dependency "rocco", "~>0.8" 19 | s.add_dependency "gli", "~>2.5" 20 | s.add_dependency "rugged", "~>1.1" 21 | s.add_dependency "redcarpet", "~>3.0" 22 | s.add_dependency "ffi-clang", "~> 0.5" 23 | s.add_dependency "parallel", "~> 1.20" 24 | s.add_development_dependency "rake", "~> 13" 25 | s.add_development_dependency "minitest", "~> 5.11" 26 | 27 | s.files = `git ls-files`.split("\n") 28 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 29 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 30 | s.require_paths = ["lib"] 31 | end 32 | 33 | -------------------------------------------------------------------------------- /lib/docurium/cli.rb: -------------------------------------------------------------------------------- 1 | class Docurium 2 | class CLI 3 | 4 | def self.doc(idir, options) 5 | doc = Docurium.new(idir, options) 6 | doc.generate_docs 7 | end 8 | 9 | def self.check(idir, options) 10 | doc = Docurium.new(idir) 11 | doc.check_warnings(options) 12 | end 13 | 14 | def self.gen(file) 15 | 16 | temp = <<-TEMPLATE 17 | { 18 | "name": "project", 19 | "github": "user/project", 20 | "input": "include/lib", 21 | "prefix": "lib_", 22 | "branch": "gh-pages" 23 | } 24 | TEMPLATE 25 | puts "Writing to #{file}" 26 | File.open(file, 'w+') do |f| 27 | f.write(temp) 28 | end 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/docurium/cparser.rb: -------------------------------------------------------------------------------- 1 | class Docurium 2 | class CParser 3 | 4 | # Remove common prefix of all lines in comment. 5 | # Otherwise tries to preserve formatting in case it is relevant. 6 | def cleanup_comment(comment) 7 | return "" unless comment 8 | 9 | lines = 0 10 | prefixed = 0 11 | shortest = nil 12 | 13 | compacted = comment.sub(/^\n+/,"").sub(/\n\s*$/, "\n") 14 | 15 | compacted.split(/\n/).each do |line| 16 | lines += 1 17 | if line =~ /^\s*\*\s*$/ || line =~ /^\s*$/ 18 | # don't count length of blank lines or lines with just a " * " on 19 | # them towards shortest common prefix 20 | prefixed += 1 21 | shortest = line if shortest.nil? 22 | elsif line =~ /^(\s*\*\s*)/ 23 | prefixed += 1 24 | shortest = $1 if shortest.nil? || shortest.length > $1.length 25 | end 26 | end 27 | 28 | if shortest =~ /\s$/ 29 | shortest = Regexp.quote(shortest.chop) + "[ \t]" 30 | elsif shortest 31 | shortest = Regexp.quote(shortest) 32 | end 33 | 34 | if lines == prefixed && !shortest.nil? && shortest.length > 0 35 | if shortest =~ /\*/ 36 | return comment.gsub(/^#{shortest}/, "").gsub(/^\s*\*\s*\n/, "\n") 37 | else 38 | return comment.gsub(/^#{shortest}/, "") 39 | end 40 | else 41 | return comment 42 | end 43 | end 44 | 45 | # Find the shortest common prefix of an array of strings 46 | def shortest_common_prefix(arr) 47 | arr.inject do |pfx,str| 48 | pfx = pfx.chop while pfx != str[0...pfx.length]; pfx 49 | end 50 | end 51 | 52 | # Match #define A(B) or #define A 53 | # and convert a series of simple #defines into an enum 54 | def detect_define(d) 55 | if d[:body] =~ /\A\#\s*define\s+((\w+)\([^\)]+\))/ 56 | d[:type] = :macro 57 | d[:decl] = $1.strip 58 | d[:name] = $2 59 | d[:tdef] = nil 60 | elsif d[:body] =~ /\A\#\s*define\s+(\w+)/ 61 | names = [] 62 | d[:body].scan(/\#\s*define\s+(\w+)/) { |m| names << m[0].to_s } 63 | d[:tdef] = nil 64 | names.uniq! 65 | if names.length == 1 66 | d[:type] = :define 67 | d[:decl] = names[0] 68 | d[:name] = names[0] 69 | elsif names.length > 1 70 | d[:type] = :enum 71 | d[:decl] = names 72 | d[:name] = shortest_common_prefix(names) 73 | d[:name].sub!(/_*$/, '') 74 | end 75 | end 76 | end 77 | 78 | # Take a multi-line #define and join into a simple definition 79 | def join_define(text) 80 | text = text.split("\n\n", 2).first || "" 81 | 82 | # Ruby 1.8 does not support negative lookbehind regex so let's 83 | # get the joined macro definition a slightly more awkward way 84 | text.split(/\s*\n\s*/).inject("\\") do |val, line| 85 | (val[-1] == ?\\) ? val = val.chop.strip + " " + line : val 86 | end.strip.gsub(/^\s*\\*\s*/, '') 87 | end 88 | 89 | # Process #define A(B) macros 90 | def parse_macro(d) 91 | if d[:body] =~ /define\s+#{Regexp.quote(d[:name])}\([^\)]*\)[ \t]*(.*)/m 92 | d[:value] = join_define($1) 93 | end 94 | d[:comments] = d[:rawComments].strip 95 | end 96 | 97 | # Process #define A ... macros 98 | def parse_define(d) 99 | if d[:body] =~ /define\s+#{Regexp.quote(d[:name])}[ \t]*(.*)/ 100 | d[:value] = join_define($1) 101 | end 102 | d[:comments] = d[:rawComments].strip 103 | end 104 | 105 | # Match enum {} (and possibly a typedef thereof) 106 | def detect_enum(d) 107 | if d[:body] =~ /\A(typedef)?\s*enum\s*\{([^\}]+)\}\s*([^;]+)?;/i 108 | typedef, values, name = $1, $2, $3 109 | d[:type] = :enum 110 | d[:decl] = values.strip.split(/\s*,\s*/).map do |v| 111 | v.split(/\s*=\s*/)[0].strip 112 | end 113 | if typedef.nil? 114 | d[:name] = shortest_common_prefix(d[:decl]) 115 | d[:name].sub!(/_*$/, '') 116 | # Using the common prefix for grouping enum values is a little 117 | # overly aggressive in some cases. If we ended up with too short 118 | # a prefix or a prefix which is too generic, then skip it. 119 | d[:name] = nil unless d[:name].scan('_').length > 1 120 | else 121 | d[:name] = name 122 | end 123 | d[:tdef] = typedef 124 | end 125 | end 126 | 127 | # Process enum definitions 128 | def parse_enum(d) 129 | if d[:decl].respond_to? :map 130 | d[:block] = d[:decl].map { |v| v.strip }.join("\n") 131 | else 132 | d[:block] = d[:decl] 133 | end 134 | d[:comments] = d[:rawComments].strip 135 | end 136 | 137 | # Match struct {} (and typedef thereof) or opaque struct typedef 138 | def detect_struct(d) 139 | if d[:body] =~ /\A(typedef)?\s*struct\s*(\w+)?\s*\{([^\}]+)\}\s*([^;]+)?/i 140 | typedef, name1, fields, name2 = $1, $2, $3, $4 141 | d[:type] = :struct 142 | d[:name] = typedef.nil? ? name1 : name2; 143 | d[:tdef] = typedef 144 | d[:decl] = fields.strip.split(/\s*\;\s*/).map do |x| 145 | x.strip.gsub(/\s+/, " ").gsub(/\(\s+/,"(") 146 | end 147 | elsif d[:body] =~ /\A(typedef)\s+struct\s+\w+\s+(\w+)/ 148 | d[:type] = :struct 149 | d[:decl] = "" 150 | d[:name] = $2 151 | d[:tdef] = $1 152 | end 153 | end 154 | 155 | # Process struct definition 156 | def parse_struct(d) 157 | if d[:decl].respond_to? :map 158 | d[:block] = d[:decl].map { |v| v.strip }.join("\n") 159 | else 160 | d[:block] = d[:decl] 161 | end 162 | d[:comments] = d[:rawComments].strip 163 | end 164 | 165 | # Match other typedefs, checking explicitly for function pointers 166 | # but otherwise just trying to extract a name as simply as possible. 167 | def detect_typedef(d) 168 | if d[:body] =~ /\Atypedef\s+([^;]+);/ 169 | d[:decl] = $1.strip 170 | if d[:decl] =~ /\S+\s+\(\*([^\)]+)\)\(/ 171 | d[:type] = :fnptr 172 | d[:name] = $1 173 | else 174 | d[:type] = :typedef 175 | d[:name] = d[:decl].split(/\s+/).last 176 | end 177 | end 178 | end 179 | 180 | # Process typedef definition 181 | def parse_typedef(d) 182 | d[:comments] = d[:rawComments].strip 183 | end 184 | 185 | # Process function pointer typedef definition 186 | def parse_fnptr(d) 187 | d[:comments] = d[:rawComments].strip 188 | end 189 | 190 | # Match function prototypes or inline function declarations 191 | def detect_function(d) 192 | if d[:body] =~ /[;\{]/ 193 | d[:type] = :file 194 | d[:decl] = "" 195 | 196 | proto = d[:body].split(/[;\{]/, 2).first.strip 197 | if proto[-1] == ?) 198 | (proto.length - 1).downto(0) do |p| 199 | tail = proto[p .. -1] 200 | if tail.count(")") == tail.count("(") 201 | if proto[0..p] =~ /(\w+)\(\z/ 202 | d[:name] = $1 203 | d[:type] = :function 204 | d[:decl] = proto 205 | end 206 | break 207 | end 208 | end 209 | end 210 | end 211 | end 212 | 213 | # Process function prototype and comments 214 | def parse_function(d) 215 | d[:args] = [] 216 | 217 | rval, argline = d[:decl].split(/\s*#{Regexp.quote(d[:name])}\(\s*/, 2) 218 | 219 | # clean up rval if it is like "extern static int" or "GIT_EXTERN(int)" 220 | while rval =~ /[A-Za-z0-9_]+\(([^\)]+)\)$/i 221 | rval = $1 222 | end 223 | rval.gsub!(/extern|static/, '') 224 | rval.strip! 225 | d[:return] = { :type => rval } 226 | 227 | # we removed the opening parenthesis, which this is expecting 228 | argline = '(' + argline 229 | # clean up argline 230 | argline = argline.slice(1..-2) while argline[0] == ?( && argline[-1] == ?) 231 | d[:argline] = argline.strip 232 | d[:args] = [] 233 | left = 0 234 | 235 | # parse argline 236 | (0 .. argline.length).each do |i| 237 | next unless argline[i] == ?, || argline.length == i 238 | 239 | s = argline.slice(left .. i) 240 | next unless s.count("(") == s.count(")") 241 | 242 | s.chop! if argline[i] == ?, 243 | s.strip! 244 | 245 | if s =~ /\(\s*\*\s*(\w+)\s*\)\s*\(/ 246 | argname = $1 247 | d[:args] << { 248 | :name => argname, 249 | :type => s.sub(/\s*#{Regexp.quote(argname)}\s*/, '').strip 250 | } 251 | elsif s =~ /\W(\w+)$/ 252 | argname = $1 253 | d[:args] << { 254 | :name => argname, 255 | :type => s[0 ... - argname.length].strip, 256 | } 257 | else 258 | # argline is probably something like "(void)" 259 | end 260 | 261 | left = i + 1 262 | end 263 | 264 | # parse comments 265 | if d[:rawComments] =~ /\@(param|return)/i 266 | d[:args].each do |arg| 267 | param_comment = /\@param\s+#{Regexp.quote(arg[:name])}/.match(d[:rawComments]) 268 | if param_comment 269 | after = param_comment.post_match 270 | end_comment = after.index(/(?:@param|@return|\Z)/) 271 | arg[:comment] = after[0 ... end_comment].strip.gsub(/\s+/, ' ') 272 | end 273 | end 274 | 275 | return_comment = /\@return\s+/.match(d[:rawComments]) 276 | if return_comment 277 | after = return_comment.post_match 278 | d[:return][:comment] = after[0 ... after.index(/(?:@param|\Z)/)].strip.gsub(/\s+/, ' ') 279 | end 280 | else 281 | # support for TomDoc params 282 | end 283 | 284 | # add in inline parameter comments 285 | if d[:inlines] # array of [param line]/[comment] pairs 286 | d[:inlines].each do |inl| 287 | d[:args].find do |arg| 288 | if inl[0] =~ /\b#{Regexp.quote(arg[:name])}$/ 289 | arg[:comment] += "\n#{inl[1]}" 290 | end 291 | end 292 | end 293 | end 294 | 295 | # generate function signature 296 | d[:sig] = d[:args].map { |a| a[:type].to_s }.join('::') 297 | 298 | # pull off function description 299 | if d[:rawComments] =~ /^\s*(public|internal|deprecated):/i 300 | # support for TomDoc description 301 | else 302 | desc, comments = d[:rawComments].split("\n\n", 2) 303 | d[:description] = desc.strip 304 | d[:comments] = comments || "" 305 | params_start = d[:comments].index(/\s?\@(?:param|return)/) 306 | d[:comments] = d[:comments].slice(0, params_start) if params_start 307 | end 308 | end 309 | 310 | # Match otherwise unrecognized commented blocks 311 | def detect_catchall(d) 312 | d[:type] = :file 313 | d[:decl] = "" 314 | end 315 | 316 | # Process comment blocks that are only associated with the whole file. 317 | def parse_file(d) 318 | m = [] 319 | d[:brief] = m[1] if m = /@brief (.*?)$/.match(d[:rawComments]) 320 | d[:defgroup] = m[1] if m = /@defgroup (.*?)$/.match(d[:rawComments]) 321 | d[:ingroup] = m[1] if m = /@ingroup (.*?)$/.match(d[:rawComments]) 322 | comments = d[:rawComments].gsub(/^@.*$/, '').strip + "\n" 323 | if d[:comments] 324 | d[:comments] = d[:comments].strip + "\n\n" + comments 325 | else 326 | d[:comments] = comments 327 | end 328 | end 329 | 330 | # Array of detectors to execute in order 331 | DETECTORS = %w(define enum struct typedef function catchall) 332 | 333 | # Given a commented chunk of file, try to parse it. 334 | def parse_declaration_block(d) 335 | # skip uncommented declarations 336 | return unless d[:rawComments].length > 0 337 | 338 | # remove inline comments in declaration 339 | while comment = d[:body].index("/*") do 340 | end_comment = d[:body].index("*/", comment) 341 | d[:body].slice!(comment, end_comment - comment + 2) 342 | end 343 | 344 | # if there are multiple #ifdef'ed declarations, we'll just 345 | # strip out the #if/#ifdef and use the first one 346 | d[:body].sub!(/[^\n]+\n/, '') if d[:body] =~ /\A\#\s*if/ 347 | 348 | # try detectors until one assigns a :type to the declaration 349 | # it's going to be one of: 350 | # - :define -> #defines + convert a series of simple ones to :enum 351 | # - :enum -> (typedef)? enum { ... }; 352 | # - :struct -> (typedef)? struct { ... }; 353 | # - :fnptr -> typedef x (*fn)(...); 354 | # - :typedef -> typedef x y; (not enum, struct, fnptr) 355 | # - :function -> rval something(like this); 356 | # - :file -> everything else goes to "file" scope 357 | DETECTORS.find { |p| method("detect_#{p}").call(d); d.has_key?(:type) } 358 | 359 | # if we detected something, call a parser for that type of thing 360 | method("parse_#{d[:type]}").call(d) if d[:type] 361 | end 362 | 363 | # Parse a chunk of text as a header file 364 | def parse_text(filename, content) 365 | # break into comments and non-comments with line numbers 366 | content = "/** */" + content if content[0..2] != "/**" 367 | recs = [] 368 | lineno = 1 369 | openblock = false 370 | 371 | content.split(/\/\*\*/).each do |chunk| 372 | c, b = chunk.split(/[ \t]*\*\//, 2) 373 | next unless c || b 374 | 375 | lineno += c.scan("\n").length if c 376 | 377 | # special handling for /**< ... */ inline comments or 378 | # for /** ... */ inside an open block 379 | if openblock || c[0] == ?< 380 | c = c.sub(/^, '').strip 381 | 382 | so_far = recs[-1][:body] 383 | last_line = so_far[ so_far.rindex("\n")+1 .. -1 ].strip.chomp(",").chomp(";") 384 | if last_line.empty? && b =~ /^([^;]+)\;/ # apply to this line instead 385 | last_line = $1.strip.chomp(",").chomp(";") 386 | end 387 | 388 | if !last_line.empty? 389 | recs[-1][:inlines] ||= [] 390 | recs[-1][:inlines] << [ last_line, c ] 391 | if b 392 | recs[-1][:body] += b 393 | lineno += b.scan("\n").length 394 | openblock = false if b =~ /\}/ 395 | end 396 | next 397 | end 398 | end 399 | 400 | # make comment have a uniform " *" prefix if needed 401 | if c !~ /\A[ \t]*\n/ && c =~ /^(\s*\*)/ 402 | c = $1 + c 403 | end 404 | 405 | # check for unterminated { brace (to handle inline comments later) 406 | openblock = true if b =~ /\{[^\}]+\Z/ 407 | 408 | recs << { 409 | :file => filename, 410 | :line => lineno + (b.start_with?("\n") ? 1 : 0), 411 | :body => b, 412 | :rawComments => cleanup_comment(c), 413 | } 414 | 415 | lineno += b.scan("\n").length if b 416 | end 417 | 418 | # try parsers on each chunk of commented header 419 | recs.each do |r| 420 | r[:body].strip! 421 | r[:rawComments].strip! 422 | r[:lineto] = r[:line] + r[:body].scan("\n").length 423 | parse_declaration_block(r) 424 | end 425 | 426 | recs 427 | end 428 | end 429 | end 430 | -------------------------------------------------------------------------------- /lib/docurium/css.css: -------------------------------------------------------------------------------- 1 | /*--------------------- Layout and Typography ----------------------------*/ 2 | body { 3 | font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; 4 | font-size: 16px; 5 | line-height: 24px; 6 | color: #252519; 7 | margin: 0; padding: 0; 8 | } 9 | a { 10 | color: #261a3b; 11 | } 12 | a:visited { 13 | color: #261a3b; 14 | } 15 | p { 16 | margin: 0 0 15px 0; 17 | } 18 | h1, h2, h3, h4, h5, h6 { 19 | margin: 40px 0 15px 0; 20 | } 21 | h2, h3, h4, h5, h6 { 22 | margin-top: 0; 23 | } 24 | #container { 25 | position: relative; 26 | } 27 | #background { 28 | position: fixed; 29 | top: 0; left: 580px; right: 0; bottom: 0; 30 | background: #f5f5ff; 31 | border-left: 1px solid #e5e5ee; 32 | z-index: -1; 33 | } 34 | #jump_to, #jump_page { 35 | background: white; 36 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 37 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 38 | font: 10px Arial; 39 | text-transform: uppercase; 40 | cursor: pointer; 41 | text-align: right; 42 | } 43 | #jump_to, #jump_wrapper { 44 | position: fixed; 45 | right: 0; top: 0; 46 | padding: 5px 10px; 47 | } 48 | #jump_wrapper { 49 | padding: 0; 50 | display: none; 51 | } 52 | #jump_to:hover #jump_wrapper { 53 | display: block; 54 | } 55 | #jump_page { 56 | padding: 5px 0 3px; 57 | margin: 0 0 25px 25px; 58 | } 59 | #jump_page .source { 60 | display: block; 61 | padding: 5px 10px; 62 | text-decoration: none; 63 | border-top: 1px solid #eee; 64 | } 65 | #jump_page .source:hover { 66 | background: #f5f5ff; 67 | } 68 | #jump_page .source:first-child { 69 | } 70 | table td { 71 | border: 0; 72 | outline: 0; 73 | } 74 | td.docs, th.docs { 75 | max-width: 500px; 76 | min-width: 500px; 77 | min-height: 5px; 78 | padding: 10px 25px 1px 50px; 79 | vertical-align: top; 80 | text-align: left; 81 | } 82 | .docs pre { 83 | margin: 15px 0 15px; 84 | padding-left: 15px; 85 | } 86 | .docs p tt, .docs p code { 87 | background: #f8f8ff; 88 | border: 1px solid #dedede; 89 | font-size: 12px; 90 | padding: 0 0.2em; 91 | } 92 | .octowrap { 93 | position: relative; 94 | } 95 | .octothorpe { 96 | font: 12px Arial; 97 | text-decoration: none; 98 | color: #454545; 99 | position: absolute; 100 | top: 3px; left: -20px; 101 | padding: 1px 2px; 102 | opacity: 0; 103 | -webkit-transition: opacity 0.2s linear; 104 | } 105 | td.docs:hover .octothorpe { 106 | opacity: 1; 107 | } 108 | td.code, th.code { 109 | padding: 14px 15px 16px 50px; 110 | width: 100%; 111 | vertical-align: top; 112 | background: #f5f5ff; 113 | border-left: 1px solid #e5e5ee; 114 | } 115 | .code pre, .docs p code { 116 | font-size: 12px; 117 | } 118 | pre, tt, code { 119 | line-height: 18px; 120 | font-family: Monaco, Consolas, "Lucida Console", monospace; 121 | margin: 0; padding: 0; 122 | } 123 | 124 | 125 | /*---------------------- Syntax Highlighting -----------------------------*/ 126 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 127 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 128 | body .hll { background-color: #ffffcc } 129 | body .c { color: #408080; font-style: italic } /* Comment */ 130 | body .err { border: 1px solid #FF0000 } /* Error */ 131 | body .k { color: #954121 } /* Keyword */ 132 | body .o { color: #666666 } /* Operator */ 133 | body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 134 | body .cp { color: #BC7A00 } /* Comment.Preproc */ 135 | body .c1 { color: #408080; font-style: italic } /* Comment.Single */ 136 | body .cs { color: #408080; font-style: italic } /* Comment.Special */ 137 | body .gd { color: #A00000 } /* Generic.Deleted */ 138 | body .ge { font-style: italic } /* Generic.Emph */ 139 | body .gr { color: #FF0000 } /* Generic.Error */ 140 | body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 141 | body .gi { color: #00A000 } /* Generic.Inserted */ 142 | body .go { color: #808080 } /* Generic.Output */ 143 | body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 144 | body .gs { font-weight: bold } /* Generic.Strong */ 145 | body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 146 | body .gt { color: #0040D0 } /* Generic.Traceback */ 147 | body .kc { color: #954121 } /* Keyword.Constant */ 148 | body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ 149 | body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ 150 | body .kp { color: #954121 } /* Keyword.Pseudo */ 151 | body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ 152 | body .kt { color: #B00040 } /* Keyword.Type */ 153 | body .m { color: #666666 } /* Literal.Number */ 154 | body .s { color: #219161 } /* Literal.String */ 155 | body .na { color: #7D9029 } /* Name.Attribute */ 156 | body .nb { color: #954121 } /* Name.Builtin */ 157 | body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 158 | body .no { color: #880000 } /* Name.Constant */ 159 | body .nd { color: #AA22FF } /* Name.Decorator */ 160 | body .ni { color: #999999; font-weight: bold } /* Name.Entity */ 161 | body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 162 | body .nf { color: #0000FF } /* Name.Function */ 163 | body .nl { color: #A0A000 } /* Name.Label */ 164 | body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 165 | body .nt { color: #954121; font-weight: bold } /* Name.Tag */ 166 | body .nv { color: #19469D } /* Name.Variable */ 167 | body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 168 | body .w { color: #bbbbbb } /* Text.Whitespace */ 169 | body .mf { color: #666666 } /* Literal.Number.Float */ 170 | body .mh { color: #666666 } /* Literal.Number.Hex */ 171 | body .mi { color: #666666 } /* Literal.Number.Integer */ 172 | body .mo { color: #666666 } /* Literal.Number.Oct */ 173 | body .sb { color: #219161 } /* Literal.String.Backtick */ 174 | body .sc { color: #219161 } /* Literal.String.Char */ 175 | body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ 176 | body .s2 { color: #219161 } /* Literal.String.Double */ 177 | body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 178 | body .sh { color: #219161 } /* Literal.String.Heredoc */ 179 | body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 180 | body .sx { color: #954121 } /* Literal.String.Other */ 181 | body .sr { color: #BB6688 } /* Literal.String.Regex */ 182 | body .s1 { color: #219161 } /* Literal.String.Single */ 183 | body .ss { color: #19469D } /* Literal.String.Symbol */ 184 | body .bp { color: #954121 } /* Name.Builtin.Pseudo */ 185 | body .vc { color: #19469D } /* Name.Variable.Class */ 186 | body .vg { color: #19469D } /* Name.Variable.Global */ 187 | body .vi { color: #19469D } /* Name.Variable.Instance */ 188 | body .il { color: #666666 } /* Literal.Number.Integer.Long */ 189 | 190 | -------------------------------------------------------------------------------- /lib/docurium/debug.rb: -------------------------------------------------------------------------------- 1 | $debug_stack = [false] 2 | 3 | def debug_enabled 4 | $debug_stack[-1] 5 | end 6 | 7 | def debug(str = nil) 8 | puts str if debug_enabled 9 | end 10 | 11 | def debug_enable 12 | $debug_stack.push true 13 | end 14 | 15 | def debug_silence 16 | $debug_stack.push false 17 | end 18 | 19 | def debug_set val 20 | $debug_stack.push val 21 | end 22 | 23 | def debug_pass 24 | $debug_stack.push debug_enabled 25 | end 26 | 27 | def debug_restore 28 | $debug_stack.pop 29 | end 30 | 31 | def with_debug(&block) 32 | debug_enable 33 | block.call 34 | debug_restore 35 | end 36 | 37 | def without_debug(&block) 38 | debug_silence 39 | block.call 40 | debug_restore 41 | end -------------------------------------------------------------------------------- /lib/docurium/docparser.rb: -------------------------------------------------------------------------------- 1 | require 'tempfile' 2 | require 'fileutils' 3 | require 'ffi/clang' 4 | require 'open3' 5 | include FFI::Clang 6 | 7 | class Docurium 8 | class DocParser 9 | # The include directory where clang has its basic type definitions is not 10 | # included in our default search path, so as a workaround we execute clang 11 | # in verbose mode and grab its include paths from the output. 12 | def find_clang_includes 13 | @includes ||= 14 | begin 15 | clang = if ENV["LLVM_CONFIG"] 16 | bindir = `#{ENV["LLVM_CONFIG"]} --bindir`.strip 17 | "#{bindir}/clang" 18 | else 19 | "clang" 20 | end 21 | 22 | output, _status = Open3.capture2e("#{clang} -v -x c -", :stdin_data => "") 23 | includes = [] 24 | output.each_line do |line| 25 | if line =~ %r{^\s+/(.*usr|.*lib/clang.*)/include} 26 | includes << line.strip 27 | end 28 | end 29 | 30 | includes 31 | end 32 | end 33 | 34 | def self.with_files(files, opts = {}) 35 | parser = self.new(files, opts) 36 | yield parser 37 | parser.cleanup! 38 | end 39 | 40 | def initialize(files, opts = {}) 41 | # unfortunately Clang wants unsaved files to exist on disk, so 42 | # we need to create at least empty files for each unsaved file 43 | # we're given. 44 | 45 | prefix = (opts[:prefix] ? opts[:prefix] + "-" : nil) 46 | @tmpdir = Dir.mktmpdir(prefix) 47 | @unsaved = files.map do |name, contents| 48 | full_path = File.join(@tmpdir, name) 49 | dirname = File.dirname(full_path) 50 | FileUtils.mkdir_p(dirname) unless Dir.exist? dirname 51 | File.new(full_path, File::CREAT).close() 52 | UnsavedFile.new(full_path, contents) 53 | end 54 | end 55 | 56 | def cleanup! 57 | FileUtils.remove_entry(@tmpdir) 58 | end 59 | 60 | # Entry point for this parser 61 | # Parse `filename` out of the hash `files` 62 | def parse_file(orig_filename, opts = {}) 63 | 64 | includes = find_clang_includes + [@tmpdir] 65 | 66 | # Override the path we want to filter by 67 | filename = File.join(@tmpdir, orig_filename) 68 | debug_enable if opts[:debug] 69 | debug "parsing #{filename} #{@tmpdir}" 70 | args = includes.map { |path| "-I#{path}" } 71 | args << '-ferror-limit=1' 72 | 73 | tu = Index.new(true, true).parse_translation_unit(filename, args, @unsaved, {:detailed_preprocessing_record => 1}) 74 | 75 | recs = [] 76 | 77 | tu.cursor.visit_children do |cursor, parent| 78 | location = cursor.location 79 | next :continue if location.file == nil 80 | next :continue unless location.file == filename 81 | 82 | loc = "%d:%d-%d:%d" % [cursor.extent.start.line, cursor.extent.start.column, cursor.extent.end.line, cursor.extent.end.column] 83 | debug "#{cursor.location.file}:#{loc} - visiting #{cursor.kind}: #{cursor.spelling}, comment is #{cursor.comment.kind}" 84 | 85 | #cursor.visit_children do |c| 86 | # puts " child #{c.kind}, #{c.spelling}, #{c.comment.kind}" 87 | # :continue 88 | #end 89 | 90 | next :continue if cursor.comment.kind == :comment_null 91 | next :continue if cursor.spelling == "" 92 | 93 | extent = cursor.extent 94 | rec = { 95 | :file => orig_filename, 96 | :line => extent.start.line, 97 | :lineto => extent.end.line, 98 | :tdef => nil, 99 | } 100 | 101 | extract = case cursor.kind 102 | when :cursor_function 103 | debug "have function #{cursor.spelling}" 104 | rec.update extract_function(cursor) 105 | when :cursor_enum_decl 106 | debug "have enum #{cursor.spelling}" 107 | rec.update extract_enum(cursor) 108 | when :cursor_struct 109 | debug "have struct #{cursor.spelling}" 110 | rec.update extract_struct(cursor) 111 | when :cursor_typedef_decl 112 | debug "have typedef #{cursor.spelling} #{cursor.underlying_type.spelling}" 113 | rec.update extract_typedef(cursor) 114 | else 115 | raise "No idea how to deal with #{cursor.kind}" 116 | end 117 | 118 | rec.merge! extract 119 | 120 | recs << rec 121 | :continue 122 | end 123 | 124 | if debug_enabled 125 | puts "parse_file: parsed #{recs.size} records for #{filename}:" 126 | recs.each do |r| 127 | puts "\t#{r}" 128 | end 129 | end 130 | 131 | debug_restore 132 | 133 | recs 134 | end 135 | 136 | def extract_typedef(cursor) 137 | child = nil 138 | cursor.visit_children { |c| child = c; :break } 139 | rec = { 140 | :name => cursor.spelling, 141 | :underlying_type => cursor.underlying_type.spelling, 142 | :tdef => :typedef, 143 | } 144 | 145 | if not child 146 | return rec 147 | end 148 | 149 | #puts "have typedef #{child.kind}, #{cursor.extent.start.line}" 150 | case child.kind 151 | when :cursor_type_ref 152 | #puts "pure typedef, #{cursor.spelling}" 153 | if child.type.kind == :type_record 154 | rec[:type] = :struct 155 | subject, desc = extract_subject_desc(cursor.comment) 156 | rec[:decl] = cursor.spelling 157 | rec[:description] = subject 158 | rec[:comments] = desc 159 | else 160 | rec[:name] = cursor.spelling 161 | end 162 | when :cursor_enum_decl 163 | rec.merge! extract_enum(child) 164 | when :cursor_struct 165 | #puts "typed struct, #{cursor.spelling}" 166 | rec.merge! extract_struct(child) 167 | when :cursor_parm_decl 168 | rec.merge! extract_function(cursor) 169 | rec[:type] = :callback 170 | # this is wasteful, but we don't get the array from outside 171 | cmt = extract_function_comment(cursor.comment) 172 | ret = { 173 | :type => extract_callback_result(rec[:underlying_type]), 174 | :comment => cmt[:return] 175 | } 176 | rec[:return] = ret 177 | else 178 | raise "No idea how to handle #{child.kind}" 179 | end 180 | # let's make sure we override the empty name the extract 181 | # functions stored 182 | rec[:name] = cursor.spelling 183 | rec 184 | end 185 | 186 | def extract_callback_result(type) 187 | type[0..(type.index('(') - 1)].strip 188 | end 189 | 190 | def extract_function_args(cursor, cmt) 191 | # We only want to look at parm_decl to avoid looking at a return 192 | # struct as a parameter 193 | children(cursor) 194 | .select {|c| c.kind == :cursor_parm_decl } 195 | .map do |arg| 196 | { 197 | :name => arg.display_name, 198 | :type => arg.type.spelling, 199 | :comment => cmt[:args][arg.display_name], 200 | } 201 | end 202 | end 203 | 204 | def extract_subject_desc(comment) 205 | subject = comment.child.text 206 | debug "\t\tsubject: #{subject}" 207 | paras = comment.find_all { |cmt| cmt.kind == :comment_paragraph }.drop(1).map { |p| p.text } 208 | desc = paras.join("\n\n") 209 | debug "\t\tdesc: #{desc}" 210 | return subject, desc 211 | end 212 | 213 | def extract_function(cursor) 214 | comment = cursor.comment 215 | 216 | $buggy_functions = %w() 217 | debug_set ($buggy_functions.include? cursor.spelling) 218 | if debug_enabled 219 | puts "\tlooking at function #{cursor.spelling}, #{cursor.display_name}" 220 | puts "\tcomment: #{comment}, #{comment.kind}" 221 | cursor.visit_children do |cur, parent| 222 | puts "\t\tchild: #{cur.spelling}, #{cur.kind}" 223 | :continue 224 | end 225 | end 226 | 227 | cmt = extract_function_comment(comment) 228 | args = extract_function_args(cursor, cmt) 229 | #args = args.reject { |arg| arg[:comment].nil? } 230 | 231 | ret = { 232 | :type => cursor.result_type.spelling, 233 | :comment => cmt[:return] 234 | } 235 | 236 | # generate function signature 237 | sig = args.map { |a| a[:type].to_s }.join('::') 238 | 239 | argline = args.map { |a| 240 | # pointers don't have a separation between '*' and the name 241 | if a[:type].end_with? "*" 242 | "#{a[:type]}#{a[:name]}" 243 | else 244 | "#{a[:type]} #{a[:name]}" 245 | end 246 | }.join(', ') 247 | 248 | decl = "#{ret[:type]} #{cursor.spelling}(#{argline})" 249 | body = "#{decl};" 250 | 251 | debug_restore 252 | #puts cursor.display_name 253 | # Return the format that docurium expects 254 | { 255 | :type => :function, 256 | :name => cursor.spelling, 257 | :body => body, 258 | :description => cmt[:description], 259 | :comments => cmt[:comments], 260 | :sig => sig, 261 | :args => args, 262 | :return => ret, 263 | :decl => decl, 264 | :argline => argline 265 | } 266 | end 267 | 268 | def extract_function_comment(comment) 269 | subject, desc = extract_subject_desc(comment) 270 | debug "\t\textract_function_comment: #{comment}, #{comment.kind}, #{subject}, #{desc}" 271 | 272 | args = {} 273 | (comment.find_all { |cmt| cmt.kind == :comment_param_command }).each do |param| 274 | args[param.name] = param.comment.strip 275 | end 276 | 277 | ret = nil 278 | comment.each do |block| 279 | next unless block.kind == :comment_block_command 280 | next unless block.name == "return" 281 | 282 | ret = block.paragraph.text 283 | 284 | break 285 | end 286 | 287 | { 288 | :description => subject, 289 | :comments => desc, 290 | :args => args, 291 | :return => ret, 292 | } 293 | end 294 | 295 | def extract_fields(cursor) 296 | fields = [] 297 | cursor.visit_children do |cchild, cparent| 298 | field = { 299 | :type => cchild.type.spelling, 300 | :name => cchild.spelling, 301 | :comments => cchild.comment.find_all {|c| c.kind == :comment_paragraph }.map(&:text).join("\n\n") 302 | } 303 | 304 | if cursor.kind == :cursor_enum_decl 305 | field.merge!({:value => cchild.enum_value}) 306 | end 307 | 308 | fields << field 309 | :continue 310 | end 311 | 312 | fields 313 | end 314 | 315 | def extract_enum(cursor) 316 | subject, desc = extract_subject_desc(cursor.comment) 317 | 318 | decl = [] 319 | cursor.visit_children do |cchild, cparent| 320 | decl << cchild.spelling 321 | :continue 322 | end 323 | 324 | block = decl.join("\n") 325 | #return the docurium object 326 | { 327 | :type => :enum, 328 | :name => cursor.spelling, 329 | :description => subject, 330 | :comments => desc, 331 | :fields => extract_fields(cursor), 332 | :block => block, 333 | :decl => decl, 334 | } 335 | end 336 | 337 | def extract_struct(cursor) 338 | subject, desc = extract_subject_desc(cursor.comment) 339 | 340 | values = [] 341 | cursor.visit_children do |cchild, cparent| 342 | values << "#{cchild.type.spelling} #{cchild.spelling}" 343 | :continue 344 | end 345 | 346 | debug "\tstruct value #{values}" 347 | 348 | rec = { 349 | :type => :struct, 350 | :name => cursor.spelling, 351 | :description => subject, 352 | :comments => desc, 353 | :fields => extract_fields(cursor), 354 | :decl => values, 355 | } 356 | 357 | rec[:block] = values.join("\n") unless values.empty? 358 | rec 359 | end 360 | 361 | def children(cursor) 362 | list = [] 363 | cursor.visit_children do |ccursor, cparent| 364 | list << ccursor 365 | :continue 366 | end 367 | 368 | list 369 | end 370 | 371 | end 372 | end 373 | -------------------------------------------------------------------------------- /lib/docurium/layout.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |{{ title }} |
30 | 31 | |
---|---|
37 |
38 | ¶
39 |
40 | {{{ docs }}}
41 | |
42 |
43 | {{{ code }}} |
45 |
Get a read-only buffer with the raw content of a blob.
\n", func[:description] 126 | assert_equal 'const void *', func[:return][:type] 127 | assert_equal ' the pointer; NULL if the blob has no contents', func[:return][:comment] 128 | assert_equal 84, func[:line] 129 | assert_equal 84, func[:lineto] 130 | assert_equal 'blob.h', func[:file] 131 | assert_equal 'git_blob *blob',func[:argline] 132 | assert_equal 'blob', func[:args][0][:name] 133 | assert_equal 'git_blob *', func[:args][0][:type] 134 | assert_equal 'pointer to the blob', func[:args][0][:comment] 135 | end 136 | 137 | def test_can_parse_defined_functions 138 | func = @data[:functions]['git_tree_lookup'] 139 | assert_equal 'int', func[:return][:type] 140 | assert_equal ' 0 on success; error code otherwise', func[:return][:comment] 141 | assert_equal 50, func[:line] 142 | assert_equal 'tree.h', func[:file] 143 | assert_equal 'id', func[:args][2][:name] 144 | assert_equal 'const git_oid *', func[:args][2][:type] 145 | assert_equal 'identity of the tree to locate.', func[:args][2][:comment] 146 | end 147 | 148 | def test_can_parse_function_cast_args 149 | func = @data[:functions]['git_reference_listcb'] 150 | assert_equal 'int', func[:return][:type] 151 | assert_equal ' 0 on success; error code otherwise', func[:return][:comment] 152 | assert_equal 321, func[:line] 153 | assert_equal 'refs.h', func[:file] 154 | assert_equal 'repo', func[:args][0][:name] 155 | assert_equal 'git_repository *', func[:args][0][:type] 156 | assert_equal 'list_flags', func[:args][1][:name] 157 | assert_equal 'unsigned int', func[:args][1][:type] 158 | assert_equal 'callback', func[:args][2][:name] 159 | assert_equal 'int (*)(const char *, void *)', func[:args][2][:type] 160 | assert_equal 'Function which will be called for every listed ref', func[:args][2][:comment] 161 | expect_comment =<<-EOF 162 |The listed references may be filtered by type, or using
163 | a bitwise OR of several types. Use the magic value
164 | GIT_REF_LISTALL
to obtain all references, including
165 | packed ones.
The callback
function will be called for each of the references
168 | in the repository, and will receive the name of the reference and
169 | the payload
value passed to this method.
This contains extra options for git_repository_init_ext
that enable
179 | additional initialization features. The fields are:
Create a new commit in the repository using git_object
\n instances as parameters.
83 | * The resulting string is "aa/...", where "aa" is the first two 84 | * hex digitis of the oid and "..." is the remaining 38 digits. 85 | * 86 | * @param str output hex string; must be pointing at the start of 87 | * the hex sequence and have at least the number of bytes 88 | * needed for an oid encoded in hex (41 bytes). Only the 89 | * oid digits are written; a '\\0' terminator must be added 90 | * by the caller if it is required. 91 | * @param oid oid structure to format. 92 | */ 93 | GIT_EXTERN(void) git_oid_pathfmt(char *str, const git_oid *oid); 94 | 95 | /** 96 | * Format a gid_oid into a newly allocated c-string. 97 | * @param oid the oid structure to format 98 | * @return the c-string; NULL if memory is exhausted. Caller must 99 | * deallocate the string with free(). 100 | */ 101 | GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *oid); 102 | 103 | /** 104 | * Format a git_oid into a buffer as a hex format c-string. 105 | *
106 | * If the buffer is smaller than GIT_OID_HEXSZ+1, then the resulting
107 | * oid c-string will be truncated to n-1 characters. If there are
108 | * any input parameter errors (out == NULL, n == 0, oid == NULL),
109 | * then a pointer to an empty string is returned, so that the return
110 | * value can always be printed.
111 | *
112 | * @param out the buffer into which the oid string is output.
113 | * @param n the size of the out buffer.
114 | * @param oid the oid structure to format.
115 | * @return the out buffer pointer, assuming no input parameter
116 | * errors, otherwise a pointer to an empty string.
117 | */
118 | GIT_EXTERN(char *) git_oid_to_string(char *out, size_t n, const git_oid *oid);
119 |
120 | /**
121 | * Copy an oid from one structure to another.
122 | * @param out oid structure the result is written into.
123 | * @param src oid structure to copy from.
124 | */
125 | GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src);
126 |
127 | /**
128 | * Compare two oid structures.
129 | * @param a first oid structure.
130 | * @param b second oid structure.
131 | * @return <0, 0, >0 if a < b, a == b, a > b.
132 | */
133 | GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);
134 |
135 | /**
136 | * OID Shortener object
137 | */
138 | typedef struct git_oid_shorten git_oid_shorten;
139 |
140 | /**
141 | * Create a new OID shortener.
142 | *
143 | * The OID shortener is used to process a list of OIDs
144 | * in text form and return the shortest length that would
145 | * uniquely identify all of them.
146 | *
147 | * E.g. look at the result of `git log --abbrev`.
148 | *
149 | * @param min_length The minimal length for all identifiers,
150 | * which will be used even if shorter OIDs would still
151 | * be unique.
152 | * @return a `git_oid_shorten` instance, NULL if OOM
153 | */
154 | git_oid_shorten *git_oid_shorten_new(size_t min_length);
155 |
156 | /**
157 | * Add a new OID to set of shortened OIDs and calculate
158 | * the minimal length to uniquely identify all the OIDs in
159 | * the set.
160 | *
161 | * The OID is expected to be a 40-char hexadecimal string.
162 | * The OID is owned by the user and will not be modified
163 | * or freed.
164 | *
165 | * For performance reasons, there is a hard-limit of how many
166 | * OIDs can be added to a single set (around ~22000, assuming
167 | * a mostly randomized distribution), which should be enough
168 | * for any kind of program, and keeps the algorithm fast and
169 | * memory-efficient.
170 | *
171 | * Attempting to add more than those OIDs will result in a
172 | * GIT_ENOMEM error
173 | *
174 | * @param os a `git_oid_shorten` instance
175 | * @param text_oid an OID in text form
176 | * @return the minimal length to uniquely identify all OIDs
177 | * added so far to the set; or an error code (<0) if an
178 | * error occurs.
179 | */
180 | int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid);
181 |
182 | /**
183 | * Free an OID shortener instance
184 | *
185 | * @param os a `git_oid_shorten` instance
186 | */
187 | void git_oid_shorten_free(git_oid_shorten *os);
188 |
189 | /** @} */
190 | GIT_END_DECL
191 | #endif
192 |
--------------------------------------------------------------------------------
/test/fixtures/git2/refs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_refs_h__
26 | #define INCLUDE_git_refs_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 | #include "oid.h"
31 |
32 | /**
33 | * @file git2/refs.h
34 | * @brief Git reference management routines
35 | * @defgroup git_reference Git reference management routines
36 | * @ingroup Git
37 | * @{
38 | */
39 | GIT_BEGIN_DECL
40 |
41 | /**
42 | * Lookup a reference by its name in a repository.
43 | *
44 | * The generated reference is owned by the repository and
45 | * should not be freed by the user.
46 | *
47 | * @param reference_out pointer to the looked-up reference
48 | * @param repo the repository to look up the reference
49 | * @param name the long name for the reference (e.g. HEAD, ref/heads/master, refs/tags/v0.1.0, ...)
50 | * @return 0 on success; error code otherwise
51 | */
52 | GIT_EXTERN(int) git_reference_lookup(git_reference **reference_out, git_repository *repo, const char *name);
53 |
54 | /**
55 | * Create a new symbolic reference.
56 | *
57 | * The reference will be created in the repository and written
58 | * to the disk.
59 | *
60 | * This reference is owned by the repository and shall not
61 | * be free'd by the user.
62 | *
63 | * @param ref_out Pointer to the newly created reference
64 | * @param repo Repository where that reference will live
65 | * @param name The name of the reference
66 | * @param target The target of the reference
67 | * @return 0 on success; error code otherwise
68 | */
69 | GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target);
70 |
71 | /**
72 | * Create a new symbolic reference, overwriting an existing one with
73 | * the same name, if it exists.
74 | *
75 | * If the new reference isn't a symbolic one, any pointers to the old
76 | * reference become invalid.
77 | *
78 | * The reference will be created in the repository and written
79 | * to the disk.
80 | *
81 | * This reference is owned by the repository and shall not
82 | * be free'd by the user.
83 | *
84 | * @param ref_out Pointer to the newly created reference
85 | * @param repo Repository where that reference will live
86 | * @param name The name of the reference
87 | * @param target The target of the reference
88 | * @return 0 on success; error code otherwise
89 | */
90 | GIT_EXTERN(int) git_reference_create_symbolic_f(git_reference **ref_out, git_repository *repo, const char *name, const char *target);
91 |
92 | /**
93 | * Create a new object id reference.
94 | *
95 | * The reference will be created in the repository and written
96 | * to the disk.
97 | *
98 | * This reference is owned by the repository and shall not
99 | * be free'd by the user.
100 | *
101 | * @param ref_out Pointer to the newly created reference
102 | * @param repo Repository where that reference will live
103 | * @param name The name of the reference
104 | * @param id The object id pointed to by the reference.
105 | * @return 0 on success; error code otherwise
106 | */
107 | GIT_EXTERN(int) git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id);
108 |
109 | /**
110 | * Create a new object id reference, overwriting an existing one with
111 | * the same name, if it exists.
112 | *
113 | * If the new reference isn't an object id one, any pointers to the
114 | * old reference become invalid.
115 | *
116 | * The reference will be created in the repository and written
117 | * to the disk.
118 | *
119 | * This reference is owned by the repository and shall not
120 | * be free'd by the user.
121 | *
122 | * @param ref_out Pointer to the newly created reference
123 | * @param repo Repository where that reference will live
124 | * @param name The name of the reference
125 | * @param id The object id pointed to by the reference.
126 | * @return 0 on success; error code otherwise
127 | */
128 | GIT_EXTERN(int) git_reference_create_oid_f(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id);
129 |
130 | /**
131 | * Get the OID pointed to by a reference.
132 | *
133 | * Only available if the reference is direct (i.e. not symbolic)
134 | *
135 | * @param ref The reference
136 | * @return a pointer to the oid if available, NULL otherwise
137 | */
138 | GIT_EXTERN(const git_oid *) git_reference_oid(git_reference *ref);
139 |
140 | /**
141 | * Get full name to the reference pointed by this reference
142 | *
143 | * Only available if the reference is symbolic
144 | *
145 | * @param ref The reference
146 | * @return a pointer to the name if available, NULL otherwise
147 | */
148 | GIT_EXTERN(const char *) git_reference_target(git_reference *ref);
149 |
150 | /**
151 | * Get the type of a reference
152 | *
153 | * Either direct (GIT_REF_OID) or symbolic (GIT_REF_SYMBOLIC)
154 | *
155 | * @param ref The reference
156 | * @return the type
157 | */
158 | GIT_EXTERN(git_rtype) git_reference_type(git_reference *ref);
159 |
160 | /**
161 | * Get the full name of a reference
162 | *
163 | * @param ref The reference
164 | * @return the full name for the ref
165 | */
166 | GIT_EXTERN(const char *) git_reference_name(git_reference *ref);
167 |
168 | /**
169 | * Resolve a symbolic reference
170 | *
171 | * Thie method iteratively peels a symbolic reference
172 | * until it resolves to a direct reference to an OID.
173 | *
174 | * If a direct reference is passed as an argument,
175 | * that reference is returned immediately
176 | *
177 | * @param resolved_ref Pointer to the peeled reference
178 | * @param ref The reference
179 | * @return 0 on success; error code otherwise
180 | */
181 | GIT_EXTERN(int) git_reference_resolve(git_reference **resolved_ref, git_reference *ref);
182 |
183 | /**
184 | * Get the repository where a reference resides
185 | *
186 | * @param ref The reference
187 | * @return a pointer to the repo
188 | */
189 | GIT_EXTERN(git_repository *) git_reference_owner(git_reference *ref);
190 |
191 | /**
192 | * Set the symbolic target of a reference.
193 | *
194 | * The reference must be a symbolic reference, otherwise
195 | * this method will fail.
196 | *
197 | * The reference will be automatically updated in
198 | * memory and on disk.
199 | *
200 | * @param ref The reference
201 | * @param target The new target for the reference
202 | * @return 0 on success; error code otherwise
203 | */
204 | GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const char *target);
205 |
206 | /**
207 | * Set the OID target of a reference.
208 | *
209 | * The reference must be a direct reference, otherwise
210 | * this method will fail.
211 | *
212 | * The reference will be automatically updated in
213 | * memory and on disk.
214 | *
215 | * @param ref The reference
216 | * @param target The new target OID for the reference
217 | * @return 0 on success; error code otherwise
218 | */
219 | GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
220 |
221 | /**
222 | * Rename an existing reference
223 | *
224 | * This method works for both direct and symbolic references.
225 | * The new name will be checked for validity and may be
226 | * modified into a normalized form.
227 | *
228 | * The refernece will be immediately renamed in-memory
229 | * and on disk.
230 | *
231 | */
232 | GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name);
233 |
234 | /**
235 | * Rename an existing reference, overwriting an existing one with the
236 | * same name, if it exists.
237 | *
238 | * This method works for both direct and symbolic references.
239 | * The new name will be checked for validity and may be
240 | * modified into a normalized form.
241 | *
242 | * The refernece will be immediately renamed in-memory
243 | * and on disk.
244 | *
245 | */
246 | GIT_EXTERN(int) git_reference_rename_f(git_reference *ref, const char *new_name);
247 |
248 | /**
249 | * Delete an existing reference
250 | *
251 | * This method works for both direct and symbolic references.
252 | *
253 | * The reference will be immediately removed on disk and from
254 | * memory. The given reference pointer will no longer be valid.
255 | *
256 | */
257 | GIT_EXTERN(int) git_reference_delete(git_reference *ref);
258 |
259 | /**
260 | * Pack all the loose references in the repository
261 | *
262 | * This method will load into the cache all the loose
263 | * references on the repository and update the
264 | * `packed-refs` file with them.
265 | *
266 | * Once the `packed-refs` file has been written properly,
267 | * the loose references will be removed from disk.
268 | *
269 | * WARNING: calling this method may invalidate any existing
270 | * references previously loaded on the cache.
271 | *
272 | * @param repo Repository where the loose refs will be packed
273 | * @return 0 on success; error code otherwise
274 | */
275 | GIT_EXTERN(int) git_reference_packall(git_repository *repo);
276 |
277 | /**
278 | * Fill a list with all the references that can be found
279 | * in a repository.
280 | *
281 | * The listed references may be filtered by type, or using
282 | * a bitwise OR of several types. Use the magic value
283 | * `GIT_REF_LISTALL` to obtain all references, including
284 | * packed ones.
285 | *
286 | * The string array will be filled with the names of all
287 | * references; these values are owned by the user and
288 | * should be free'd manually when no longer needed, using
289 | * `git_strarray_free`.
290 | *
291 | * @param array Pointer to a git_strarray structure where
292 | * the reference names will be stored
293 | * @param repo Repository where to find the refs
294 | * @param list_flags Filtering flags for the reference
295 | * listing.
296 | * @return 0 on success; error code otherwise
297 | */
298 | GIT_EXTERN(int) git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags);
299 |
300 |
301 | /**
302 | * List all the references in the repository, calling a custom
303 | * callback for each one.
304 | *
305 | * The listed references may be filtered by type, or using
306 | * a bitwise OR of several types. Use the magic value
307 | * `GIT_REF_LISTALL` to obtain all references, including
308 | * packed ones.
309 | *
310 | * The `callback` function will be called for each of the references
311 | * in the repository, and will receive the name of the reference and
312 | * the `payload` value passed to this method.
313 | *
314 | * @param repo Repository where to find the refs
315 | * @param list_flags Filtering flags for the reference
316 | * listing.
317 | * @param callback Function which will be called for every listed ref
318 | * @param payload Additional data to pass to the callback
319 | * @return 0 on success; error code otherwise
320 | */
321 | GIT_EXTERN(int) git_reference_listcb(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload);
322 |
323 | /** @} */
324 | GIT_END_DECL
325 | #endif
326 |
--------------------------------------------------------------------------------
/test/fixtures/git2/repository.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_repository_h__
26 | #define INCLUDE_git_repository_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 | #include "oid.h"
31 |
32 | /**
33 | * @file git2/repository.h
34 | * @brief Git repository management routines
35 | * @defgroup git_repository Git repository management routines
36 | * @ingroup Git
37 | * @{
38 | */
39 | GIT_BEGIN_DECL
40 |
41 | /**
42 | * Open a git repository.
43 | *
44 | * The 'path' argument must point to an existing git repository
45 | * folder, e.g.
46 | *
47 | * /path/to/my_repo/.git/ (normal repository)
48 | * objects/
49 | * index
50 | * HEAD
51 | *
52 | * /path/to/bare_repo/ (bare repository)
53 | * objects/
54 | * index
55 | * HEAD
56 | *
57 | * The method will automatically detect if 'path' is a normal
58 | * or bare repository or fail is 'path' is neither.
59 | *
60 | * @param repository pointer to the repo which will be opened
61 | * @param path the path to the repository
62 | * @return 0 on success; error code otherwise
63 | */
64 | GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *path);
65 |
66 |
67 | /**
68 | * Open a git repository by manually specifying all its paths
69 | *
70 | * @param repository pointer to the repo which will be opened
71 | *
72 | * @param git_dir The full path to the repository folder
73 | * e.g. a '.git' folder for live repos, any folder for bare
74 | * Equivalent to $GIT_DIR.
75 | * Cannot be NULL.
76 | *
77 | * @param git_object_directory The full path to the ODB folder.
78 | * the folder where all the loose and packed objects are stored
79 | * Equivalent to $GIT_OBJECT_DIRECTORY.
80 | * If NULL, "$GIT_DIR/objects/" is assumed.
81 | *
82 | * @param git_index_file The full path to the index (dircache) file
83 | * Equivalent to $GIT_INDEX_FILE.
84 | * If NULL, "$GIT_DIR/index" is assumed.
85 | *
86 | * @param git_work_tree The full path to the working tree of the repository,
87 | * if the repository is not bare.
88 | * Equivalent to $GIT_WORK_TREE.
89 | * If NULL, the repository is assumed to be bare.
90 | *
91 | * @return 0 on success; error code otherwise
92 | */
93 | GIT_EXTERN(int) git_repository_open2(git_repository **repository,
94 | const char *git_dir,
95 | const char *git_object_directory,
96 | const char *git_index_file,
97 | const char *git_work_tree);
98 |
99 |
100 | /**
101 | * Open a git repository by manually specifying its paths and
102 | * the object database it will use.
103 | *
104 | * @param repository pointer to the repo which will be opened
105 | *
106 | * @param git_dir The full path to the repository folder
107 | * e.g. a '.git' folder for live repos, any folder for bare
108 | * Equivalent to $GIT_DIR.
109 | * Cannot be NULL.
110 | *
111 | * @param object_database A pointer to a git_odb created & initialized
112 | * by the user (e.g. with custom backends). This object database
113 | * will be owned by the repository and will be automatically free'd.
114 | * It should not be manually free'd by the user, or this
115 | * git_repository object will become invalid.
116 | *
117 | * @param git_index_file The full path to the index (dircache) file
118 | * Equivalent to $GIT_INDEX_FILE.
119 | * If NULL, "$GIT_DIR/index" is assumed.
120 | *
121 | * @param git_work_tree The full path to the working tree of the repository,
122 | * if the repository is not bare.
123 | * Equivalent to $GIT_WORK_TREE.
124 | * If NULL, the repository is assumed to be bare.
125 | *
126 | * @return 0 on success; error code otherwise
127 | */
128 |
129 | GIT_EXTERN(int) git_repository_open3(git_repository **repository,
130 | const char *git_dir,
131 | git_odb *object_database,
132 | const char *git_index_file,
133 | const char *git_work_tree);
134 |
135 | /**
136 | * Get the object database behind a Git repository
137 | *
138 | * @param repo a repository object
139 | * @return a pointer to the object db
140 | */
141 | GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo);
142 |
143 | /**
144 | * Get the Index file of a Git repository
145 | *
146 | * This is a cheap operation; the index is only opened on the first call,
147 | * and subsequent calls only retrieve the previous pointer.
148 | *
149 | * @param index Pointer where to store the index
150 | * @param repo a repository object
151 | * @return 0 on success; error code if the index could not be opened
152 | */
153 | GIT_EXTERN(int) git_repository_index(git_index **index, git_repository *repo);
154 |
155 | /**
156 | * Free a previously allocated repository
157 | *
158 | * Note that after a repository is free'd, all the objects it has spawned
159 | * will still exist until they are manually closed by the user
160 | * with `git_object_close`, but accessing any of the attributes of
161 | * an object without a backing repository will result in undefined
162 | * behavior
163 | *
164 | * @param repo repository handle to close. If NULL nothing occurs.
165 | */
166 | GIT_EXTERN(void) git_repository_free(git_repository *repo);
167 |
168 | /**
169 | * Creates a new Git repository in the given folder.
170 | *
171 | * TODO:
172 | * - Reinit the repository
173 | * - Create config files
174 | *
175 | * @param repo_out pointer to the repo which will be created or reinitialized
176 | * @param path the path to the repository
177 | * @param is_bare if true, a Git repository without a working directory is created
178 | * at the pointed path. If false, provided path will be considered as the working
179 | * directory into which the .git directory will be created.
180 | *
181 | * @return 0 on success; error code otherwise
182 | */
183 | GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
184 |
185 | /**
186 | * Check if a repository is empty
187 | *
188 | * An empty repository has just been initialized and contains
189 | * no commits.
190 | *
191 | * @param repo Repo to test
192 | * @return 1 if the repository is empty, 0 if it isn't, error code
193 | * if the repository is corrupted
194 | */
195 | GIT_EXTERN(int) git_repository_is_empty(git_repository *repo);
196 |
197 | /**
198 | * Get the normalized path to the git repository.
199 | *
200 | * @param repo a repository object
201 | * @return absolute path to the git directory
202 | */
203 | GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
204 |
205 | /**
206 | * Get the normalized path to the working directory of the repository.
207 | *
208 | * If the repository is bare, there is no working directory and NULL we be returned.
209 | *
210 | * @param repo a repository object
211 | * @return NULL if the repository is bare; absolute path to the working directory otherwise.
212 | */
213 | GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
214 |
215 | /**
216 | * Extended options structure for `git_repository_init_ext`.
217 | *
218 | * This contains extra options for `git_repository_init_ext` that enable
219 | * additional initialization features. The fields are:
220 | *
221 | * * flags - Combination of GIT_REPOSITORY_INIT flags above.
222 | * * mode - Set to one of the standard GIT_REPOSITORY_INIT_SHARED_...
223 | * constants above, or to a custom value that you would like.
224 | * * workdir_path - The path to the working dir or NULL for default (i.e.
225 | * repo_path parent on non-bare repos). IF THIS IS RELATIVE PATH,
226 | * IT WILL BE EVALUATED RELATIVE TO THE REPO_PATH. If this is not
227 | * the "natural" working directory, a .git gitlink file will be
228 | * created here linking to the repo_path.
229 | * * description - If set, this will be used to initialize the "description"
230 | * file in the repository, instead of using the template content.
231 | * * template_path - When GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE is set,
232 | * this contains the path to use for the template directory. If
233 | * this is NULL, the config or default directory options will be
234 | * used instead.
235 | * * initial_head - The name of the head to point HEAD at. If NULL, then
236 | * this will be treated as "master" and the HEAD ref will be set
237 | * to "refs/heads/master". If this begins with "refs/" it will be
238 | * used verbatim; otherwise "refs/heads/" will be prefixed.
239 | * * origin_url - If this is non-NULL, then after the rest of the
240 | * repository initialization is completed, an "origin" remote
241 | * will be added pointing to this URL.
242 | */
243 | typedef struct {
244 | unsigned int version;
245 | uint32_t flags;
246 | uint32_t mode;
247 | const char *workdir_path;
248 | const char *description;
249 | const char *template_path;
250 | const char *initial_head;
251 | const char *origin_url;
252 | } git_repository_init_options;
253 |
254 | /** @} */
255 | GIT_END_DECL
256 | #endif
257 |
--------------------------------------------------------------------------------
/test/fixtures/git2/revwalk.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_revwalk_h__
26 | #define INCLUDE_git_revwalk_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 | #include "oid.h"
31 |
32 | /**
33 | * @file git2/revwalk.h
34 | * @brief Git revision traversal routines
35 | * @defgroup git_revwalk Git revision traversal routines
36 | * @ingroup Git
37 | * @{
38 | */
39 | GIT_BEGIN_DECL
40 |
41 | /**
42 | * Sort the repository contents in no particular ordering;
43 | * this sorting is arbitrary, implementation-specific
44 | * and subject to change at any time.
45 | * This is the default sorting for new walkers.
46 | */
47 | #define GIT_SORT_NONE (0)
48 |
49 | /**
50 | * Sort the repository contents in topological order
51 | * (parents before children); this sorting mode
52 | * can be combined with time sorting.
53 | */
54 | #define GIT_SORT_TOPOLOGICAL (1 << 0)
55 |
56 | /**
57 | * Sort the repository contents by commit time;
58 | * this sorting mode can be combined with
59 | * topological sorting.
60 | */
61 | #define GIT_SORT_TIME (1 << 1)
62 |
63 | /**
64 | * Iterate through the repository contents in reverse
65 | * order; this sorting mode can be combined with
66 | * any of the above.
67 | */
68 | #define GIT_SORT_REVERSE (1 << 2)
69 |
70 | /**
71 | * Allocate a new revision walker to iterate through a repo.
72 | *
73 | * This revision walker uses a custom memory pool and an internal
74 | * commit cache, so it is relatively expensive to allocate.
75 | *
76 | * For maximum performance, this revision walker should be
77 | * reused for different walks.
78 | *
79 | * This revision walker is *not* thread safe: it may only be
80 | * used to walk a repository on a single thread; however,
81 | * it is possible to have several revision walkers in
82 | * several different threads walking the same repository.
83 | *
84 | * @param walker pointer to the new revision walker
85 | * @param repo the repo to walk through
86 | * @return 0 on success; error code otherwise
87 | */
88 | GIT_EXTERN(int) git_revwalk_new(git_revwalk **walker, git_repository *repo);
89 |
90 | /**
91 | * Reset the revision walker for reuse.
92 | *
93 | * This will clear all the pushed and hidden commits, and
94 | * leave the walker in a blank state (just like at
95 | * creation) ready to receive new commit pushes and
96 | * start a new walk.
97 | *
98 | * The revision walk is automatically reset when a walk
99 | * is over.
100 | *
101 | * @param walker handle to reset.
102 | */
103 | GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
104 |
105 | /**
106 | * Mark a commit to start traversal from.
107 | *
108 | * The given OID must belong to a commit on the walked
109 | * repository.
110 | *
111 | * The given commit will be used as one of the roots
112 | * when starting the revision walk. At least one commit
113 | * must be pushed the repository before a walk can
114 | * be started.
115 | *
116 | * @param walker the walker being used for the traversal.
117 | * @param oid the oid of the commit to start from.
118 | * @return 0 on success; error code otherwise
119 | */
120 | GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *oid);
121 |
122 |
123 | /**
124 | * Mark a commit (and its ancestors) uninteresting for the output.
125 | *
126 | * The given OID must belong to a commit on the walked
127 | * repository.
128 | *
129 | * The resolved commit and all its parents will be hidden from the
130 | * output on the revision walk.
131 | *
132 | * @param walker the walker being used for the traversal.
133 | * @param commit the commit that will be ignored during the traversal
134 | * @return 0 on success; error code otherwise
135 | */
136 | GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *oid);
137 |
138 | /**
139 | * Get the next commit from the revision walk.
140 | *
141 | * The initial call to this method is *not* blocking when
142 | * iterating through a repo with a time-sorting mode.
143 | *
144 | * Iterating with Topological or inverted modes makes the initial
145 | * call blocking to preprocess the commit list, but this block should be
146 | * mostly unnoticeable on most repositories (topological preprocessing
147 | * times at 0.3s on the git.git repo).
148 | *
149 | * The revision walker is reset when the walk is over.
150 | *
151 | * @param oid Pointer where to store the oid of the next commit
152 | * @param walk the walker to pop the commit from.
153 | * @return GIT_SUCCESS if the next commit was found;
154 | * GIT_EREVWALKOVER if there are no commits left to iterate
155 | */
156 | GIT_EXTERN(int) git_revwalk_next(git_oid *oid, git_revwalk *walk);
157 |
158 | /**
159 | * Change the sorting mode when iterating through the
160 | * repository's contents.
161 | *
162 | * Changing the sorting mode resets the walker.
163 | *
164 | * @param walk the walker being used for the traversal.
165 | * @param sort_mode combination of GIT_SORT_XXX flags
166 | */
167 | GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode);
168 |
169 | /**
170 | * Free a revision walker previously allocated.
171 | *
172 | * @param walk traversal handle to close. If NULL nothing occurs.
173 | */
174 | GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk);
175 |
176 | /**
177 | * Return the repository on which this walker
178 | * is operating.
179 | *
180 | * @param walk the revision walker
181 | * @return the repository being walked
182 | */
183 | GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk);
184 |
185 | /** @} */
186 | GIT_END_DECL
187 | #endif
188 |
--------------------------------------------------------------------------------
/test/fixtures/git2/signature.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_signature_h__
26 | #define INCLUDE_git_signature_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 |
31 | /**
32 | * @file git2/signature.h
33 | * @brief Git signature creation
34 | * @defgroup git_signature Git signature creation
35 | * @ingroup Git
36 | * @{
37 | */
38 | GIT_BEGIN_DECL
39 |
40 | /**
41 | * Create a new action signature. The signature must be freed
42 | * manually or using git_signature_free
43 | *
44 | * @param name name of the person
45 | * @param mail email of the person
46 | * @param time time when the action happened
47 | * @param offset timezone offset in minutes for the time
48 | * @return the new sig, NULL on out of memory
49 | */
50 | GIT_EXTERN(git_signature *) git_signature_new(const char *name, const char *email, git_time_t time, int offset);
51 |
52 | /**
53 | * Create a new action signature with a timestamp of 'now'. The
54 | * signature must be freed manually or using git_signature_free
55 | *
56 | * @param name name of the person
57 | * @param email email of the person
58 | * @return the new sig, NULL on out of memory
59 | */
60 | GIT_EXTERN(git_signature *) git_signature_now(const char *name, const char *email);
61 |
62 |
63 | /**
64 | * Create a copy of an existing signature.
65 | *
66 | * All internal strings are also duplicated.
67 | * @param sig signature to duplicated
68 | * @return a copy of sig, NULL on out of memory
69 | */
70 | GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig);
71 |
72 | /**
73 | * Free an existing signature
74 | *
75 | * @param sig signature to free
76 | */
77 | GIT_EXTERN(void) git_signature_free(git_signature *sig);
78 |
79 | /** @} */
80 | GIT_END_DECL
81 | #endif
82 |
--------------------------------------------------------------------------------
/test/fixtures/git2/tag.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_tag_h__
26 | #define INCLUDE_git_tag_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 | #include "oid.h"
31 | #include "object.h"
32 |
33 | /**
34 | * @file git2/tag.h
35 | * @brief Git tag parsing routines
36 | * @defgroup git_tag Git tag management
37 | * @ingroup Git
38 | * @{
39 | */
40 | GIT_BEGIN_DECL
41 |
42 | /**
43 | * Lookup a tag object from the repository.
44 | *
45 | * @param tag pointer to the looked up tag
46 | * @param repo the repo to use when locating the tag.
47 | * @param id identity of the tag to locate.
48 | * @return 0 on success; error code otherwise
49 | */
50 | GIT_INLINE(int) git_tag_lookup(git_tag **tag, git_repository *repo, const git_oid *id)
51 | {
52 | return git_object_lookup((git_object **)tag, repo, id, (git_otype)GIT_OBJ_TAG);
53 | }
54 |
55 | /**
56 | * Close an open tag
57 | *
58 | * This is a wrapper around git_object_close()
59 | *
60 | * IMPORTANT:
61 | * It *is* necessary to call this method when you stop
62 | * using a tag. Failure to do so will cause a memory leak.
63 | *
64 | * @param tag the tag to close
65 | */
66 |
67 | GIT_INLINE(void) git_tag_close(git_tag *tag)
68 | {
69 | git_object_close((git_object *) tag);
70 | }
71 |
72 |
73 | /**
74 | * Get the id of a tag.
75 | *
76 | * @param tag a previously loaded tag.
77 | * @return object identity for the tag.
78 | */
79 | GIT_EXTERN(const git_oid *) git_tag_id(git_tag *tag);
80 |
81 | /**
82 | * Get the tagged object of a tag
83 | *
84 | * This method performs a repository lookup for the
85 | * given object and returns it
86 | *
87 | * @param target pointer where to store the target
88 | * @param tag a previously loaded tag.
89 | * @return 0 on success; error code otherwise
90 | */
91 | GIT_EXTERN(int) git_tag_target(git_object **target, git_tag *t);
92 |
93 | /**
94 | * Get the OID of the tagged object of a tag
95 | *
96 | * @param tag a previously loaded tag.
97 | * @return pointer to the OID
98 | */
99 | GIT_EXTERN(const git_oid *) git_tag_target_oid(git_tag *t);
100 |
101 | /**
102 | * Get the type of a tag's tagged object
103 | *
104 | * @param tag a previously loaded tag.
105 | * @return type of the tagged object
106 | */
107 | GIT_EXTERN(git_otype) git_tag_type(git_tag *t);
108 |
109 | /**
110 | * Get the name of a tag
111 | *
112 | * @param tag a previously loaded tag.
113 | * @return name of the tag
114 | */
115 | GIT_EXTERN(const char *) git_tag_name(git_tag *t);
116 |
117 | /**
118 | * Get the tagger (author) of a tag
119 | *
120 | * @param tag a previously loaded tag.
121 | * @return reference to the tag's author
122 | */
123 | GIT_EXTERN(const git_signature *) git_tag_tagger(git_tag *t);
124 |
125 | /**
126 | * Get the message of a tag
127 | *
128 | * @param tag a previously loaded tag.
129 | * @return message of the tag
130 | */
131 | GIT_EXTERN(const char *) git_tag_message(git_tag *t);
132 |
133 |
134 | /**
135 | * Create a new tag in the repository from an OID
136 | *
137 | * @param oid Pointer where to store the OID of the
138 | * newly created tag
139 | *
140 | * @param repo Repository where to store the tag
141 | *
142 | * @param tag_name Name for the tag; this name is validated
143 | * for consistency. It should also not conflict with an
144 | * already existing tag name
145 | *
146 | * @param target OID to which this tag points; note that no
147 | * validation is done on this OID. Use the _o version of this
148 | * method to assure a proper object is being tagged
149 | *
150 | * @param target_type Type of the tagged OID; note that no
151 | * validation is performed here either
152 | *
153 | * @param tagger Signature of the tagger for this tag, and
154 | * of the tagging time
155 | *
156 | * @param message Full message for this tag
157 | *
158 | * @return 0 on success; error code otherwise.
159 | * A tag object is written to the ODB, and a proper reference
160 | * is written in the /refs/tags folder, pointing to it
161 | */
162 | GIT_EXTERN(int) git_tag_create(
163 | git_oid *oid,
164 | git_repository *repo,
165 | const char *tag_name,
166 | const git_oid *target,
167 | git_otype target_type,
168 | const git_signature *tagger,
169 | const char *message);
170 |
171 |
172 | /**
173 | * Create a new tag in the repository from an existing
174 | * `git_object` instance
175 | *
176 | * This method replaces the `target` and `target_type`
177 | * paremeters of `git_tag_create` by a single instance
178 | * of a `const git_object *`, which is assured to be
179 | * a proper object in the ODB and hence will create
180 | * a valid tag
181 | *
182 | * @see git_tag_create
183 | */
184 | GIT_EXTERN(int) git_tag_create_o(
185 | git_oid *oid,
186 | git_repository *repo,
187 | const char *tag_name,
188 | const git_object *target,
189 | const git_signature *tagger,
190 | const char *message);
191 |
192 | /**
193 | * Create a new tag in the repository from a buffer
194 | *
195 | * @param oid Pointer where to store the OID of the newly created tag
196 | *
197 | * @param repo Repository where to store the tag
198 | *
199 | * @param buffer Raw tag data
200 | */
201 | GIT_EXTERN(int) git_tag_create_frombuffer(
202 | git_oid *oid,
203 | git_repository *repo,
204 | const char *buffer);
205 |
206 | /**
207 | * Create a new tag in the repository from an OID
208 | * and overwrite an already existing tag reference, if any.
209 | *
210 | * @param oid Pointer where to store the OID of the
211 | * newly created tag
212 | *
213 | * @param repo Repository where to store the tag
214 | *
215 | * @param tag_name Name for the tag; this name is validated
216 | * for consistency.
217 | *
218 | * @param target OID to which this tag points; note that no
219 | * validation is done on this OID. Use the _fo version of this
220 | * method to assure a proper object is being tagged
221 | *
222 | * @param target_type Type of the tagged OID; note that no
223 | * validation is performed here either
224 | *
225 | * @param tagger Signature of the tagger for this tag, and
226 | * of the tagging time
227 | *
228 | * @param message Full message for this tag
229 | *
230 | * @return 0 on success; error code otherwise.
231 | * A tag object is written to the ODB, and a proper reference
232 | * is written in the /refs/tags folder, pointing to it
233 | */
234 | GIT_EXTERN(int) git_tag_create_f(
235 | git_oid *oid,
236 | git_repository *repo,
237 | const char *tag_name,
238 | const git_oid *target,
239 | git_otype target_type,
240 | const git_signature *tagger,
241 | const char *message);
242 |
243 | /**
244 | * Create a new tag in the repository from an existing
245 | * `git_object` instance and overwrite an already existing
246 | * tag reference, if any.
247 | *
248 | * This method replaces the `target` and `target_type`
249 | * paremeters of `git_tag_create_f` by a single instance
250 | * of a `const git_object *`, which is assured to be
251 | * a proper object in the ODB and hence will create
252 | * a valid tag
253 | *
254 | * @see git_tag_create_f
255 | */
256 | GIT_EXTERN(int) git_tag_create_fo(
257 | git_oid *oid,
258 | git_repository *repo,
259 | const char *tag_name,
260 | const git_object *target,
261 | const git_signature *tagger,
262 | const char *message);
263 |
264 | /**
265 | * Delete an existing tag reference.
266 | *
267 | * @param repo Repository where lives the tag
268 | *
269 | * @param tag_name Name of the tag to be deleted;
270 | * this name is validated for consistency.
271 | *
272 | * @return 0 on success; error code otherwise.
273 | */
274 | GIT_EXTERN(int) git_tag_delete(
275 | git_repository *repo,
276 | const char *tag_name);
277 |
278 | /**
279 | * Fill a list with all the tags in the Repository
280 | *
281 | * The string array will be filled with the names of the
282 | * matching tags; these values are owned by the user and
283 | * should be free'd manually when no longer needed, using
284 | * `git_strarray_free`.
285 | *
286 | * @param array Pointer to a git_strarray structure where
287 | * the tag names will be stored
288 | * @param repo Repository where to find the tags
289 | * @return 0 on success; error code otherwise
290 | */
291 | GIT_EXTERN(int) git_tag_list(
292 | git_strarray *tag_names,
293 | git_repository *repo);
294 |
295 | /** @} */
296 | GIT_END_DECL
297 | #endif
298 |
--------------------------------------------------------------------------------
/test/fixtures/git2/thread-utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_thread_utils_h__
26 | #define INCLUDE_git_thread_utils_h__
27 |
28 | /*
29 | * How TLS works is compiler+platform dependant
30 | * Sources: http://en.wikipedia.org/wiki/Thread-Specific_Storage
31 | * http://predef.sourceforge.net/precomp.html
32 | */
33 |
34 | #define GIT_HAS_TLS 1
35 |
36 | #if defined(__APPLE__) && defined(__MACH__)
37 | # undef GIT_TLS
38 | # define GIT_TLS
39 |
40 | #elif defined(__GNUC__) || \
41 | defined(__SUNPRO_C) || \
42 | defined(__SUNPRO_CC) || \
43 | defined(__xlc__) || \
44 | defined(__xlC__)
45 | # define GIT_TLS __thread
46 |
47 | #elif defined(__INTEL_COMPILER)
48 | # if defined(_WIN32) || defined(_WIN32_CE)
49 | # define GIT_TLS __declspec(thread)
50 | # else
51 | # define GIT_TLS __thread
52 | # endif
53 |
54 | #elif defined(_WIN32) || \
55 | defined(_WIN32_CE) || \
56 | defined(__BORLANDC__)
57 | # define GIT_TLS __declspec(thread)
58 |
59 | #else
60 | # undef GIT_HAS_TLS
61 | # define GIT_TLS /* nothing: tls vars are thread-global */
62 | #endif
63 |
64 | /* sparse and cygwin don't grok thread-local variables */
65 | #if defined(__CHECKER__) || defined(__CYGWIN__)
66 | # undef GIT_HAS_TLS
67 | # undef GIT_TLS
68 | # define GIT_TLS
69 | #endif
70 |
71 | #endif /* INCLUDE_git_thread_utils_h__ */
72 |
--------------------------------------------------------------------------------
/test/fixtures/git2/tree.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_tree_h__
26 | #define INCLUDE_git_tree_h__
27 |
28 | #include "common.h"
29 | #include "types.h"
30 | #include "oid.h"
31 | #include "object.h"
32 |
33 | /**
34 | * @file git2/tree.h
35 | * @brief Git tree parsing, loading routines
36 | * @defgroup git_tree Git tree parsing, loading routines
37 | * @ingroup Git
38 | * @{
39 | */
40 | GIT_BEGIN_DECL
41 |
42 | /**
43 | * Lookup a tree object from the repository.
44 | *
45 | * @param tree pointer to the looked up tree
46 | * @param repo the repo to use when locating the tree.
47 | * @param id identity of the tree to locate.
48 | * @return 0 on success; error code otherwise
49 | */
50 | GIT_INLINE(int) git_tree_lookup(git_tree **tree, git_repository *repo, const git_oid *id)
51 | {
52 | return git_object_lookup((git_object **)tree, repo, id, GIT_OBJ_TREE);
53 | }
54 |
55 | /**
56 | * Close an open tree
57 | *
58 | * This is a wrapper around git_object_close()
59 | *
60 | * IMPORTANT:
61 | * It *is* necessary to call this method when you stop
62 | * using a tree. Failure to do so will cause a memory leak.
63 | *
64 | * @param tree the tree to close
65 | */
66 |
67 | GIT_INLINE(void) git_tree_close(git_tree *tree)
68 | {
69 | git_object_close((git_object *) tree);
70 | }
71 |
72 |
73 | /**
74 | * Get the id of a tree.
75 | *
76 | * @param tree a previously loaded tree.
77 | * @return object identity for the tree.
78 | */
79 | GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree);
80 |
81 | /**
82 | * Get the number of entries listed in a tree
83 | *
84 | * @param tree a previously loaded tree.
85 | * @return the number of entries in the tree
86 | */
87 | GIT_EXTERN(size_t) git_tree_entrycount(git_tree *tree);
88 |
89 | /**
90 | * Lookup a tree entry by its filename
91 | *
92 | * @param tree a previously loaded tree.
93 | * @param filename the filename of the desired entry
94 | * @return the tree entry; NULL if not found
95 | */
96 | GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(git_tree *tree, const char *filename);
97 |
98 | /**
99 | * Lookup a tree entry by its position in the tree
100 | *
101 | * @param tree a previously loaded tree.
102 | * @param idx the position in the entry list
103 | * @return the tree entry; NULL if not found
104 | */
105 | GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, int idx);
106 |
107 | /**
108 | * Get the UNIX file attributes of a tree entry
109 | *
110 | * @param entry a tree entry
111 | * @return attributes as an integer
112 | */
113 | GIT_EXTERN(unsigned int) git_tree_entry_attributes(const git_tree_entry *entry);
114 |
115 | /**
116 | * Get the filename of a tree entry
117 | *
118 | * @param entry a tree entry
119 | * @return the name of the file
120 | */
121 | GIT_EXTERN(const char *) git_tree_entry_name(const git_tree_entry *entry);
122 |
123 | /**
124 | * Get the id of the object pointed by the entry
125 | *
126 | * @param entry a tree entry
127 | * @return the oid of the object
128 | */
129 | GIT_EXTERN(const git_oid *) git_tree_entry_id(const git_tree_entry *entry);
130 |
131 | /**
132 | * Convert a tree entry to the git_object it points too.
133 | *
134 | * @param object pointer to the converted object
135 | * @param repo repository where to lookup the pointed object
136 | * @param entry a tree entry
137 | * @return 0 on success; error code otherwise
138 | */
139 | GIT_EXTERN(int) git_tree_entry_2object(git_object **object_out, git_repository *repo, const git_tree_entry *entry);
140 |
141 | /**
142 | * Write a tree to the ODB from the index file
143 | *
144 | * This method will scan the index and write a representation
145 | * of its current state back to disk; it recursively creates
146 | * tree objects for each of the subtrees stored in the index,
147 | * but only returns the OID of the root tree. This is the OID
148 | * that can be used e.g. to create a commit.
149 | *
150 | * The index instance cannot be bare, and needs to be associated
151 | * to an existing repository.
152 | *
153 | * @param oid Pointer where to store the written tree
154 | * @param index Index to write
155 | * @return 0 on success; error code otherwise
156 | */
157 | GIT_EXTERN(int) git_tree_create_fromindex(git_oid *oid, git_index *index);
158 |
159 | /**
160 | * Create a new tree builder.
161 | *
162 | * The tree builder can be used to create or modify
163 | * trees in memory and write them as tree objects to the
164 | * database.
165 | *
166 | * If the `source` parameter is not NULL, the tree builder
167 | * will be initialized with the entries of the given tree.
168 | *
169 | * If the `source` parameter is NULL, the tree builder will
170 | * have no entries and will have to be filled manually.
171 | *
172 | * @param builder_p Pointer where to store the tree builder
173 | * @param source Source tree to initialize the builder (optional)
174 | * @return 0 on sucess; error code otherwise
175 | */
176 | GIT_EXTERN(int) git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source);
177 |
178 | /**
179 | * Clear all the entires in the builder
180 | *
181 | * @param bld Builder to clear
182 | */
183 | GIT_EXTERN(void) git_treebuilder_clear(git_treebuilder *bld);
184 |
185 | /**
186 | * Free a tree builder
187 | *
188 | * This will clear all the entries and free to builder.
189 | * Failing to free the builder after you're done using it
190 | * will result in a memory leak
191 | *
192 | * @param bld Builder to free
193 | */
194 | GIT_EXTERN(void) git_treebuilder_free(git_treebuilder *bld);
195 |
196 | /**
197 | * Get an entry from the builder from its filename
198 | *
199 | * The returned entry is owned by the builder and should
200 | * not be freed manually.
201 | *
202 | * @param bld Tree builder
203 | * @param filename Name of the entry
204 | * @return pointer to the entry; NULL if not found
205 | */
206 | GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(git_treebuilder *bld, const char *filename);
207 |
208 | /**
209 | * Add or update an entry to the builder
210 | *
211 | * Insert a new entry for `filename` in the builder with the
212 | * given attributes.
213 | *
214 | * if an entry named `filename` already exists, its attributes
215 | * will be updated with the given ones.
216 | *
217 | * The optional pointer `entry_out` can be used to retrieve a
218 | * pointer to the newly created/updated entry.
219 | *
220 | * @param entry_out Pointer to store the entry (optional)
221 | * @param bld Tree builder
222 | * @param filename Filename of the entry
223 | * @param id SHA1 oid of the entry
224 | * @param attributes Folder attributes of the entry
225 | * @return 0 on success; error code otherwise
226 | */
227 | GIT_EXTERN(int) git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes);
228 |
229 | /**
230 | * Remove an entry from the builder by its filename
231 | *
232 | * @param bld Tree builder
233 | * @param filename Filename of the entry to remove
234 | */
235 | GIT_EXTERN(int) git_treebuilder_remove(git_treebuilder *bld, const char *filename);
236 |
237 | /**
238 | * Filter the entries in the tree
239 | *
240 | * The `filter` callback will be called for each entry
241 | * in the tree with a pointer to the entry and the
242 | * provided `payload`: if the callback returns 1, the
243 | * entry will be filtered (removed from the builder).
244 | *
245 | * @param bld Tree builder
246 | * @param filter Callback to filter entries
247 | */
248 | GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload);
249 |
250 | /**
251 | * Write the contents of the tree builder as a tree object
252 | *
253 | * The tree builder will be written to the given `repo`, and
254 | * it's identifying SHA1 hash will be stored in the `oid`
255 | * pointer.
256 | *
257 | * @param oid Pointer where to store the written OID
258 | * @param repo Repository where to store the object
259 | * @param bld Tree builder to write
260 | * @return 0 on success; error code otherwise
261 | */
262 | GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld);
263 |
264 | /** @} */
265 | GIT_END_DECL
266 | #endif
267 |
--------------------------------------------------------------------------------
/test/fixtures/git2/types.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License, version 2,
4 | * as published by the Free Software Foundation.
5 | *
6 | * In addition to the permissions in the GNU General Public License,
7 | * the authors give you unlimited permission to link the compiled
8 | * version of this file into combinations with other programs,
9 | * and to distribute those combinations without any restriction
10 | * coming from the use of this file. (The General Public License
11 | * restrictions do apply in other respects; for example, they cover
12 | * modification of the file, and distribution when not linked into
13 | * a combined executable.)
14 | *
15 | * This file is distributed in the hope that it will be useful, but
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | * General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License
21 | * along with this program; see the file COPYING. If not, write to
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 | * Boston, MA 02110-1301, USA.
24 | */
25 | #ifndef INCLUDE_git_types_h__
26 | #define INCLUDE_git_types_h__
27 |
28 | #include "common.h"
29 |
30 | /**
31 | * @file git2/types.h
32 | * @brief libgit2 base & compatibility types
33 | * @ingroup Git
34 | * @{
35 | */
36 | GIT_BEGIN_DECL
37 |
38 | /**
39 | * Cross-platform compatibility types for off_t / time_t
40 | *
41 | * NOTE: This needs to be in a public header so that both the library
42 | * implementation and client applications both agree on the same types.
43 | * Otherwise we get undefined behavior.
44 | *
45 | * Use the "best" types that each platform provides. Currently we truncate
46 | * these intermediate representations for compatibility with the git ABI, but
47 | * if and when it changes to support 64 bit types, our code will naturally
48 | * adapt.
49 | * NOTE: These types should match those that are returned by our internal
50 | * stat() functions, for all platforms.
51 | */
52 | #include