Index: lib/buildr/packaging/artifact.rb
===================================================================
--- lib/buildr/packaging/artifact.rb	(revision 883432)
+++ lib/buildr/packaging/artifact.rb	Thu Feb 11 11:21:51 CET 2010
@@ -44,8 +44,20 @@
       def included(mod)
         mod.extend self
       end
+
+      public
+      def lookup_upload_task(uri)
+        @upload_tasks ||= {}
+        @upload_tasks[uri]
-    end
+      end
 
+      def register_upload_task(uri, task)
+        @upload_tasks ||= {}
+        @upload_tasks[uri] = task
+        task
+      end
+    end
+
     # The artifact identifier.
     attr_reader :id
     # The group identifier.
@@ -153,15 +165,14 @@
     # In the third form, uses a hash with the options :url, :username, :password,
     # and :permissions. All but :url are optional.
     def upload(upload_to = nil)
-      # Where do we release to?
+      upload_task(upload_to).invoke
+    end
+
+    def upload_task(upload_to = nil)
       upload_to ||= Buildr.repositories.release_to
       upload_to = { :url=>upload_to } unless Hash === upload_to
       raise ArgumentError, 'Don\'t know where to upload, perhaps you forgot to set repositories.release_to' unless upload_to[:url]
-      invoke # Make sure we exist.
 
-      # Upload POM ahead of package, so we don't fail and find POM-less package (the horror!)
-      pom.upload(upload_to) if pom && pom != self
-
       # Set the upload URI, including mandatory slash (we expect it to be the base directory).
       # Username/password may be part of URI, or separate entities.
       uri = URI.parse(upload_to[:url].clone)
@@ -169,11 +180,21 @@
       uri.user = upload_to[:username] if upload_to[:username]
       uri.password = upload_to[:password] if upload_to[:password]
 
+      path = group.gsub('.', '/') + "/#{id}/#{version}/#{File.basename(name)}"
+
+      unless task = ActsAsArtifact.lookup_upload_task(uri+path)
+        deps = [self]
+        deps << pom.upload_task( upload_to ) if pom && pom != self
+
+        task = Rake::Task.define_task uri + path => deps do
-      # Upload artifact relative to base URL, need to create path before uploading.
-      info "Deploying #{to_spec}"
+          # Upload artifact relative to base URL, need to create path before uploading.
+          info "Deploying #{to_spec}"
-      path = group.gsub('.', '/') + "/#{id}/#{version}/#{File.basename(name)}"
-      URI.upload uri + path, name, :permissions=>upload_to[:permissions]
-    end
+          URI.upload uri + path, name, :permissions=>upload_to[:permissions]
+        end
+        ActsAsArtifact.register_upload_task uri + path, task
+      end
+      task
+    end
 
   protected
 
Index: lib/buildr/packaging/package.rb
===================================================================
--- lib/buildr/packaging/package.rb	(revision 902243)
+++ lib/buildr/packaging/package.rb	Thu Feb 11 11:15:03 CET 2010
@@ -192,7 +192,7 @@
 
         task('install')   { package.install if package.respond_to?(:install) }
         task('uninstall') { package.uninstall if package.respond_to?(:uninstall) }
-        task('upload')    { package.upload if package.respond_to?(:upload) }
+        task('upload' => package.upload_task ) if package.respond_to?(:upload_task)
 
         packages << package
       end
