<commit_before>---
layout: default
title: Artifacts
---


In Buildr, almost everything is a file or a file task. You compile source files that come from the file system using dependencies found on the file system, generating even more files. But how do you get these dependencies to start with, and how do you share them with others?

Artifacts. We designed Buildr to work as a drop-in replacement for Maven 2.0, and share artifacts through the same local and remote repositories. Artifact tasks know how to download a file from one of the remote repositories, and install it in the local repository, where Buildr can find it. Packages know how to create files and upload them to remote repositories.

We'll get into all of that in a second, but first, let's introduce the artifact specification. It's a simple string that takes one of two forms:

{% highlight text %}
group:id:type:version
group:id:type:classifier:version
{% endhighlight %}

For example, @'org.apache.axis2:axis2:jar:1.2'@ refers to an artifact with group identifier org.apache.axis2, artifact identifier axis2, a JAR file with version 1.2.  Classifiers are typically used to distinguish between similar file types, for example, a source distribution and a binary distribution that otherwise have the same identifier and are both ZIP files.


h2(#specifying). Specifying Artifacts

If your Buildfile spells out @'org.apache.axis2:axis2:jar:1.2'@ more than once, you're doing something wrong.  Repeating the same string over and over will make your code harder to maintain.  You'll know that when you upgrade to a new version in one place, forget to do it in another, and end up with a mismatch.

You can use Ruby's syntax to do simple string substitution, for example:

{% highlight ruby %}
AXIS_VERSION = '1.2'

compile.with "org.apache.axis2:axis2:jar:#{AXIS_VERSION}"
{% endhighlight %}

Better yet, you can define all your artifacts at the top of the Buildfile and use constants to reference them in your project definition.  For example:

{% highlight ruby %}
AXIS2 = 'org.apache.axis2:axis2:jar:1.2'

compile.with AXIS2
{% endhighlight %}

Note that we're not using a separate constant for the version number.  In our experience, it's unnecessary.  The version number intentionally appears at the end of the string, where it stands out easily.

If you have a set of artifacts that belong to the same group and version, and that's quite common, you can use the @group@ shortcut:

{% highlight ruby %}
AXIOM  = group('axiom-api', 'axiom-impl', 'axiom-dom',
  :under=>'org.apache.ws.commons.axiom', :version=>'1.2.4')
{% endhighlight %}

p(note). Buildr projects also define a @group@ attribute which can lead to some confusion.  If you want to define an artifact group within a project definition, you should use the explicit qualifier @Buildr::group@.

If you have several artifacts you always use together, consider placing them in an array.  Methods that accept lists of artifacts also accept arrays.  For example:

{% highlight ruby %}
OPENJPA = ['org.apache.openjpa:openjpa:jar:1.2.1',
  'net.sourceforge.serp:serp:jar:1.12.0']
AXIS_OF_WS = [AXIS2, AXIOM]

compile.with OPENJPA, AXIS_OF_WS
{% endhighlight %}

Another way to group related artifacts together and access them individually is using the @struct@ shortcut.  For example:

{% highlight ruby %}
JAVAX = struct(
  :activation  =>'javax.activation:activation:jar:1.1',
  :persistence =>'javax.persistence:persistence-api:jar:1.0',
  :stream      =>'stax:stax-api:jar:1.0.1',
)

compile.with JAVAX.persistence, OPENJPA
{% endhighlight %}

In our experience, using constants in this manner makes your Buildfile much easier to write and maintain.

And, of course, you can always place your artifact specifications in a separate file and require it into your Buildfile.  For example, if you're working on several different projects that all share the same artifacts:

{% highlight ruby %}
require '../shared/artifacts'
{% endhighlight %}

When you use @require@, Ruby always looks for a filename with the @.rb@ extension, so in this case it expects to find @artifacts.rb@ in the @shared@ directory.

One last thing.  You can also treat artifact specifications as hashes.  For example:

{% highlight ruby %}
AXIS = { :group=>'org.apache.axis2', :id=>'axis2', :version=>'1.2' }
compile.with AXIS
puts compile.dependencies.first.to_hash
=> { :group=>'org.apache.axis2', :id=>'axis2',
     :version=>'1.2', :type=>:jar }
{% endhighlight %}


h2(#repositories). Specifying Repositories

Buildr can download artifacts for you, but only if you tell it where to find them.  You need to specify at least one remote repository, from which to download these artifacts.

When you call @repositories.remote@, you get an array of URLs for the various remote repositories.  Initially, it's an empty array, to which you can add new repositories.  For example:

{% highlight ruby %}
repositories.remote << 'http://www.ibiblio.org/maven2/'
{% endhighlight %}

If you need to use a proxy server to access remote repositories, you can set the environment variable @HTTP_PROXY@ to the proxy server URL (use @HTTPS_PROXY@ for proxying HTTPS connections).  You can also work without a proxy for certain hosts by specifying the @NO_PROXY@ environment variable.  For example:

{% highlight sh %}
$ export HTTP_PROXY = 'http://myproxy:8080'
$ export NO_PROXY = '*.mycompany.com,localhost,special:800'
{% endhighlight %}

Alternatively you can use the Buildr options @proxy.http@ and @proxy.exclude@:

{% highlight ruby %}
options.proxy.http = 'http://myproxy:8080'
options.proxy.exclude << '*.mycompany.com'
options.proxy.exclude << 'localhost'
{% endhighlight %}

All the artifacts download into the local repository.  Since all your projects share the same local repository, you only need to download each artifact once. Buildr was designed to be used alongside Maven 2.0, for example, when migrating projects from Maven 2.0 over to Buildr.  By default it will share the same local repository, expecting the repository to be the @.m2/repository@ directory inside your home directory.

You can choose to relocate the local repository by giving it a different path, for example:

{% highlight ruby %}
repositories.local = '/usr/local/maven/repository'
{% endhighlight %}

That's one change you don't want to commit into the Buildfile, so the best place to do it is in the @buildr.rb@ file in the @.buildr@ directory under your home directory.

Buildr downloads artifacts when it needs to use them, for example, to compile a project.  You don't need to download artifacts directly.  Except when you do, for example, if you want to download all the latest artifacts and then go off-line.  It's as simple as:

{% highlight sh %}
$ buildr artifacts
{% endhighlight %}
<commit_msg>Add HTTP authentication example<commit_after>---
layout: default
title: Artifacts
---


In Buildr, almost everything is a file or a file task. You compile source files that come from the file system using dependencies found on the file system, generating even more files. But how do you get these dependencies to start with, and how do you share them with others?

Artifacts. We designed Buildr to work as a drop-in replacement for Maven 2.0, and share artifacts through the same local and remote repositories. Artifact tasks know how to download a file from one of the remote repositories, and install it in the local repository, where Buildr can find it. Packages know how to create files and upload them to remote repositories.

We'll get into all of that in a second, but first, let's introduce the artifact specification. It's a simple string that takes one of two forms:

{% highlight text %}
group:id:type:version
group:id:type:classifier:version
{% endhighlight %}

For example, @'org.apache.axis2:axis2:jar:1.2'@ refers to an artifact with group identifier org.apache.axis2, artifact identifier axis2, a JAR file with version 1.2.  Classifiers are typically used to distinguish between similar file types, for example, a source distribution and a binary distribution that otherwise have the same identifier and are both ZIP files.


h2(#specifying). Specifying Artifacts

If your Buildfile spells out @'org.apache.axis2:axis2:jar:1.2'@ more than once, you're doing something wrong.  Repeating the same string over and over will make your code harder to maintain.  You'll know that when you upgrade to a new version in one place, forget to do it in another, and end up with a mismatch.

You can use Ruby's syntax to do simple string substitution, for example:

{% highlight ruby %}
AXIS_VERSION = '1.2'

compile.with "org.apache.axis2:axis2:jar:#{AXIS_VERSION}"
{% endhighlight %}

Better yet, you can define all your artifacts at the top of the Buildfile and use constants to reference them in your project definition.  For example:

{% highlight ruby %}
AXIS2 = 'org.apache.axis2:axis2:jar:1.2'

compile.with AXIS2
{% endhighlight %}

Note that we're not using a separate constant for the version number.  In our experience, it's unnecessary.  The version number intentionally appears at the end of the string, where it stands out easily.

If you have a set of artifacts that belong to the same group and version, and that's quite common, you can use the @group@ shortcut:

{% highlight ruby %}
AXIOM  = group('axiom-api', 'axiom-impl', 'axiom-dom',
  :under=>'org.apache.ws.commons.axiom', :version=>'1.2.4')
{% endhighlight %}

p(note). Buildr projects also define a @group@ attribute which can lead to some confusion.  If you want to define an artifact group within a project definition, you should use the explicit qualifier @Buildr::group@.

If you have several artifacts you always use together, consider placing them in an array.  Methods that accept lists of artifacts also accept arrays.  For example:

{% highlight ruby %}
OPENJPA = ['org.apache.openjpa:openjpa:jar:1.2.1',
  'net.sourceforge.serp:serp:jar:1.12.0']
AXIS_OF_WS = [AXIS2, AXIOM]

compile.with OPENJPA, AXIS_OF_WS
{% endhighlight %}

Another way to group related artifacts together and access them individually is using the @struct@ shortcut.  For example:

{% highlight ruby %}
JAVAX = struct(
  :activation  =>'javax.activation:activation:jar:1.1',
  :persistence =>'javax.persistence:persistence-api:jar:1.0',
  :stream      =>'stax:stax-api:jar:1.0.1',
)

compile.with JAVAX.persistence, OPENJPA
{% endhighlight %}

In our experience, using constants in this manner makes your Buildfile much easier to write and maintain.

And, of course, you can always place your artifact specifications in a separate file and require it into your Buildfile.  For example, if you're working on several different projects that all share the same artifacts:

{% highlight ruby %}
require '../shared/artifacts'
{% endhighlight %}

When you use @require@, Ruby always looks for a filename with the @.rb@ extension, so in this case it expects to find @artifacts.rb@ in the @shared@ directory.

One last thing.  You can also treat artifact specifications as hashes.  For example:

{% highlight ruby %}
AXIS = { :group=>'org.apache.axis2', :id=>'axis2', :version=>'1.2' }
compile.with AXIS
puts compile.dependencies.first.to_hash
=> { :group=>'org.apache.axis2', :id=>'axis2',
     :version=>'1.2', :type=>:jar }
{% endhighlight %}


h2(#repositories). Specifying Repositories

Buildr can download artifacts for you, but only if you tell it where to find them.  You need to specify at least one remote repository, from which to download these artifacts.

When you call @repositories.remote@, you get an array of URLs for the various remote repositories.  Initially, it's an empty array, to which you can add new repositories.  For example:

{% highlight ruby %}
repositories.remote << 'http://www.ibiblio.org/maven2/'
{% endhighlight %}

If your repository requires HTTP authentication, you can write,

{% highlight ruby %}
repositories.remote << URI.parse("http://user:password@repository.example.com")
{% endhighlight %}

If you need to use a proxy server to access remote repositories, you can set the environment variable @HTTP_PROXY@ to the proxy server URL (use @HTTPS_PROXY@ for proxying HTTPS connections).  You can also work without a proxy for certain hosts by specifying the @NO_PROXY@ environment variable.  For example:

{% highlight sh %}
$ export HTTP_PROXY = 'http://myproxy:8080'
$ export NO_PROXY = '*.mycompany.com,localhost,special:800'
{% endhighlight %}

Alternatively you can use the Buildr options @proxy.http@ and @proxy.exclude@:

{% highlight ruby %}
options.proxy.http = 'http://myproxy:8080'
options.proxy.exclude << '*.mycompany.com'
options.proxy.exclude << 'localhost'
{% endhighlight %}

All the artifacts download into the local repository.  Since all your projects share the same local repository, you only need to download each artifact once. Buildr was designed to be used alongside Maven 2.0, for example, when migrating projects from Maven 2.0 over to Buildr.  By default it will share the same local repository, expecting the repository to be the @.m2/repository@ directory inside your home directory.

You can choose to relocate the local repository by giving it a different path, for example:

{% highlight ruby %}
repositories.local = '/usr/local/maven/repository'
{% endhighlight %}

That's one change you don't want to commit into the Buildfile, so the best place to do it is in the @buildr.rb@ file in the @.buildr@ directory under your home directory.

Buildr downloads artifacts when it needs to use them, for example, to compile a project.  You don't need to download artifacts directly.  Except when you do, for example, if you want to download all the latest artifacts and then go off-line.  It's as simple as:

{% highlight sh %}
$ buildr artifacts
{% endhighlight %}

{'fraction_non_alphanumeric': 0.08519755955839628, 'fraction_numerical': 0.010023242300987797, 'mean_word_length': 4.603988603988604, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3179235', 'n_tokens_mistral': 4063, 'n_tokens_neox': 3717, 'n_words': 1813}