metaforce 0.2.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.rvmrc +55 -0
- data/Gemfile +10 -0
- data/Guardfile +9 -0
- data/README.md +59 -0
- data/Rakefile +6 -0
- data/lib/metaforce.rb +4 -0
- data/lib/metaforce/api.rb +3 -0
- data/lib/metaforce/api/metadata.rb +117 -0
- data/lib/metaforce/api/services.rb +33 -0
- data/lib/metaforce/api/transaction.rb +53 -0
- data/lib/metaforce/config.rb +24 -0
- data/lib/metaforce/manifest.rb +313 -0
- data/lib/metaforce/version.rb +3 -0
- data/metaforce.gemspec +28 -0
- data/spec/.gitignore +1 -0
- data/spec/fixtures/package.xml +17 -0
- data/spec/fixtures/requests/check_deploy_status/done.xml +33 -0
- data/spec/fixtures/requests/check_deploy_status/error.xml +26 -0
- data/spec/fixtures/requests/check_status/done.xml +19 -0
- data/spec/fixtures/requests/check_status/not_done.xml +19 -0
- data/spec/fixtures/requests/deploy/in_progress.xml +13 -0
- data/spec/fixtures/requests/describe_metadata/success.xml +230 -0
- data/spec/fixtures/requests/list_metadata/objects.xml +33 -0
- data/spec/fixtures/requests/login/failure.xml +15 -0
- data/spec/fixtures/requests/login/success.xml +39 -0
- data/spec/fixtures/sample/src/classes/TestClass.cls +2 -0
- data/spec/fixtures/sample/src/classes/TestClass.cls-meta.xml +5 -0
- data/spec/fixtures/sample/src/package.xml +8 -0
- data/spec/lib/api/metadata_spec.rb +139 -0
- data/spec/lib/api/services_spec.rb +24 -0
- data/spec/lib/api/transaction_spec.rb +62 -0
- data/spec/lib/config_spec.rb +53 -0
- data/spec/lib/manifest_spec.rb +181 -0
- data/spec/spec_helper.rb +11 -0
- data/wsdl/23.0/metadata.xml +3520 -0
- data/wsdl/23.0/partner.xml +3190 -0
- metadata +167 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
|
7
|
+
environment_id="ruby-1.9.2-p290@metaforce"
|
8
|
+
|
9
|
+
#
|
10
|
+
# Uncomment following line if you want options to be set only for given project.
|
11
|
+
#
|
12
|
+
# PROJECT_JRUBY_OPTS=( --1.9 )
|
13
|
+
|
14
|
+
#
|
15
|
+
# First we attempt to load the desired environment directly from the environment
|
16
|
+
# file. This is very fast and efficient compared to running through the entire
|
17
|
+
# CLI and selector. If you want feedback on which environment was used then
|
18
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
19
|
+
#
|
20
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
|
21
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
22
|
+
then
|
23
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
24
|
+
|
25
|
+
if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
|
26
|
+
then
|
27
|
+
. "${rvm_path:-$HOME/.rvm}/hooks/after_use"
|
28
|
+
fi
|
29
|
+
else
|
30
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
31
|
+
if ! rvm --create "$environment_id"
|
32
|
+
then
|
33
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
34
|
+
return 1
|
35
|
+
fi
|
36
|
+
fi
|
37
|
+
|
38
|
+
#
|
39
|
+
# If you use an RVM gemset file to install a list of gems (*.gems), you can have
|
40
|
+
# it be automatically loaded. Uncomment the following and adjust the filename if
|
41
|
+
# necessary.
|
42
|
+
#
|
43
|
+
# filename=".gems"
|
44
|
+
# if [[ -s "$filename" ]]
|
45
|
+
# then
|
46
|
+
# rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
|
47
|
+
# fi
|
48
|
+
|
49
|
+
# If you use bundler, this might be useful to you:
|
50
|
+
# if command -v bundle && [[ -s Gemfile ]]
|
51
|
+
# then
|
52
|
+
# bundle install
|
53
|
+
# fi
|
54
|
+
|
55
|
+
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Metaforce
|
2
|
+
Metaforce is a Ruby gem for interacting with the [Salesforce Metadata API](http://www.salesforce.com/us/developer/docs/api_meta/index.htm).
|
3
|
+
The goal of this project is to make the [Migration Tool](http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_deploying_ant.htm) obsolete, favoring Rake over Ant.
|
4
|
+
|
5
|
+
Metaforce is in active development and is currently in alpha status. Don't use
|
6
|
+
it to deploy code to production instances. You've been warned!
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
```bash
|
10
|
+
gem install metaforce -v '0.2.0.alpha'
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
``` ruby
|
15
|
+
client = Metaforce::Metadata::Client.new :username => 'username',
|
16
|
+
:password => 'password',
|
17
|
+
:security_token => 'security token')
|
18
|
+
|
19
|
+
client.describe
|
20
|
+
# => { :metadata_objects => [{ :child_xml_names => "CustomLabel", :directory_name => "labels" ... }
|
21
|
+
|
22
|
+
client.list(:type => "CustomObject")
|
23
|
+
# => [{ :created_by_id => "005U0000000EGpcIAG", :created_by_name => "Eric Holmes", ... }]
|
24
|
+
|
25
|
+
deployment = client.deploy(File.expand_path("../src"))
|
26
|
+
# => #<Metaforce::Transaction:0x00000102779bf8 @id="04sU0000000WNWoIAO" @type=:deploy>
|
27
|
+
|
28
|
+
deployment.done?
|
29
|
+
# => false
|
30
|
+
|
31
|
+
deployment.result(:wait_until_done => true)
|
32
|
+
# => { :id => "04sU0000000WNWoIAO", :messages => [{ :changed => true ... :success => true }
|
33
|
+
```
|
34
|
+
|
35
|
+
## Roadmap
|
36
|
+
This gem is far from being feature complete. Here's a list of things that still
|
37
|
+
need to be done.
|
38
|
+
|
39
|
+
* Implement .retrieve for retrieving metadata.
|
40
|
+
* Implement CRUD based calls <http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_crud_based_calls_intro.htm>.
|
41
|
+
* Implement some helper methods for diffing metadata.
|
42
|
+
* And some other stuff that I haven't quite thought of yet...
|
43
|
+
|
44
|
+
## License
|
45
|
+
Copyright (C) 2012 Eric Holmes
|
46
|
+
|
47
|
+
This program is free software; you can redistribute it and/or
|
48
|
+
modify it under the terms of the GNU General Public License
|
49
|
+
as published by the Free Software Foundation; either version 2
|
50
|
+
of the License, or (at your option) any later version.
|
51
|
+
|
52
|
+
This program is distributed in the hope that it will be useful,
|
53
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
54
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
55
|
+
GNU General Public License for more details.
|
56
|
+
|
57
|
+
You should have received a copy of the GNU General Public License
|
58
|
+
along with this program; if not, write to the Free Software
|
59
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
data/Rakefile
ADDED
data/lib/metaforce.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'metaforce/manifest'
|
2
|
+
require 'savon'
|
3
|
+
require 'zip/zip'
|
4
|
+
require 'base64'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
module Metaforce
|
8
|
+
module Metadata
|
9
|
+
class Client
|
10
|
+
DEPLOY_ZIP = 'deploy.zip'
|
11
|
+
RETRIEVE_ZIP = 'retrieve.zip'
|
12
|
+
|
13
|
+
def initialize(options=nil)
|
14
|
+
@session = Services::Client.new(options).session
|
15
|
+
@client = Savon::Client.new File.expand_path("../../../../wsdl/#{Metaforce.configuration.api_version}/metadata.xml", __FILE__) do |wsdl|
|
16
|
+
wsdl.endpoint = @session[:metadata_server_url]
|
17
|
+
end
|
18
|
+
@header = {
|
19
|
+
"ins0:SessionHeader" => {
|
20
|
+
"ins0:sessionId" => @session[:session_id]
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# Specify an array of component types to list
|
26
|
+
#
|
27
|
+
# example:
|
28
|
+
# [
|
29
|
+
# { :type => "ApexClass" },
|
30
|
+
# { :type => "ApexComponent" }
|
31
|
+
# ]
|
32
|
+
def list(queries=[])
|
33
|
+
unless queries.is_a?(Array)
|
34
|
+
queries = [ queries ]
|
35
|
+
end
|
36
|
+
response = @client.request(:list_metadata) do |soap|
|
37
|
+
soap.header = @header
|
38
|
+
soap.body = {
|
39
|
+
:queries => queries
|
40
|
+
}
|
41
|
+
end
|
42
|
+
response.body[:list_metadata_response][:result]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Describe the organization's metadata
|
46
|
+
def describe
|
47
|
+
response = @client.request(:describe_metadata) do |soap|
|
48
|
+
soap.header = @header
|
49
|
+
end
|
50
|
+
response.body[:describe_metadata_response][:result]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Checks the status of an async result
|
54
|
+
#
|
55
|
+
# If type is :retrieve or :deploy, it returns the RetrieveResult or
|
56
|
+
# DeployResult, respectively
|
57
|
+
def status(ids, type=nil)
|
58
|
+
request = "check_status"
|
59
|
+
request = "check_#{type.to_s}_status" unless type.nil?
|
60
|
+
ids = [ ids ] unless ids.is_a?(Array)
|
61
|
+
|
62
|
+
response = @client.request(request.to_sym) do |soap|
|
63
|
+
soap.header = @header
|
64
|
+
soap.body = {
|
65
|
+
:ids => ids
|
66
|
+
}
|
67
|
+
end
|
68
|
+
response.body["#{request}_response".to_sym][:result]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns true if the deployment with id id is done, false otherwise
|
72
|
+
def done?(id)
|
73
|
+
self.status(id)[:done]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Deploys dir to the organisation
|
77
|
+
def deploy(dir, options={})
|
78
|
+
options = OpenStruct.new options
|
79
|
+
|
80
|
+
if dir.is_a?(String)
|
81
|
+
filename = File.join(File.dirname(dir), DEPLOY_ZIP)
|
82
|
+
zip_contents = create_deploy_file(filename, dir)
|
83
|
+
elsif dir.is_a?(File)
|
84
|
+
zip_contents = Base64.encode64(dir.read)
|
85
|
+
end
|
86
|
+
|
87
|
+
yield options if block_given?
|
88
|
+
|
89
|
+
response = @client.request(:deploy) do |soap|
|
90
|
+
soap.header = @header
|
91
|
+
soap.body = {
|
92
|
+
:zip_file => zip_contents,
|
93
|
+
:deploy_options => options.marshal_dump
|
94
|
+
}
|
95
|
+
end
|
96
|
+
Transaction.deployment self, response[:deploy_response][:result][:id]
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Creates the deploy file, reads in the contents and returns the base64
|
102
|
+
# encoded data
|
103
|
+
def create_deploy_file(filename, dir)
|
104
|
+
File.delete(filename) if File.exists?(filename)
|
105
|
+
Zip::ZipFile.open(filename, Zip::ZipFile::CREATE) do |zip|
|
106
|
+
Dir["#{dir}/**/**"].each do |file|
|
107
|
+
zip.add(file.sub(dir + '/', ''), file)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
contents = Base64.encode64(File.open(filename, "rb").read)
|
111
|
+
File.delete(filename)
|
112
|
+
contents
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'savon'
|
2
|
+
|
3
|
+
module Metaforce
|
4
|
+
module Services
|
5
|
+
class Client
|
6
|
+
attr_reader :session
|
7
|
+
|
8
|
+
def initialize(options=nil)
|
9
|
+
options = {
|
10
|
+
:username => Metaforce.configuration.username,
|
11
|
+
:password => Metaforce.configuration.password,
|
12
|
+
:security_token => Metaforce.configuration.security_token
|
13
|
+
} if options.nil?
|
14
|
+
@session = self.login(options[:username], options[:password], options[:security_token])
|
15
|
+
end
|
16
|
+
|
17
|
+
def login(username, password, security_token=nil)
|
18
|
+
password = "#{password}#{security_token}" unless security_token.nil?
|
19
|
+
client = Savon::Client.new File.expand_path("../../../../wsdl/#{Metaforce.configuration.api_version}/partner.xml", __FILE__) do |wsdl|
|
20
|
+
wsdl.endpoint = wsdl.endpoint.to_s.sub(/login/, 'test') if Metaforce.configuration.test
|
21
|
+
end
|
22
|
+
response = client.request(:login) do
|
23
|
+
soap.body = {
|
24
|
+
:username => username,
|
25
|
+
:password => password
|
26
|
+
}
|
27
|
+
end
|
28
|
+
{ :session_id => response.body[:login_response][:result][:session_id],
|
29
|
+
:metadata_server_url => response.body[:login_response][:result][:metadata_server_url] }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Metaforce
|
2
|
+
|
3
|
+
# Convenience class for deployment/retrieval results
|
4
|
+
class Transaction
|
5
|
+
attr_reader :id
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def initialize(client, id, type)
|
9
|
+
@id = id
|
10
|
+
@client = client
|
11
|
+
@type = type
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.deployment(client, id)
|
15
|
+
self.new client, id, :deploy
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.retrieval(client, id)
|
19
|
+
self.new client, id, :retrieve
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns true if the transaction has completed, false otherwise
|
23
|
+
def done?
|
24
|
+
@done = @client.done?(@id) unless @done
|
25
|
+
@done
|
26
|
+
end
|
27
|
+
alias :complete? :done?
|
28
|
+
alias :completed? :done?
|
29
|
+
|
30
|
+
# Returns the deploy or retrieve result
|
31
|
+
def result(options={})
|
32
|
+
self.wait_until_done if options[:wait_until_done]
|
33
|
+
raise "Request is not complete! Be sure to call .done? first!" unless @done
|
34
|
+
@result = @client.status(@id, @type) if @result.nil?
|
35
|
+
@result
|
36
|
+
end
|
37
|
+
|
38
|
+
# Enters a loop until .done? returns true
|
39
|
+
def wait_until_done
|
40
|
+
max_wait = 30
|
41
|
+
wait_time = 1
|
42
|
+
until self.done?
|
43
|
+
sleep(wait_time)
|
44
|
+
if wait_time < 30
|
45
|
+
wait_time *= 2
|
46
|
+
else
|
47
|
+
wait_time = max_wait
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Metaforce
|
2
|
+
class << self
|
3
|
+
def configuration
|
4
|
+
@configuration ||= Configuration.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def configure
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :api_version
|
14
|
+
attr_accessor :username
|
15
|
+
attr_accessor :password
|
16
|
+
attr_accessor :security_token
|
17
|
+
attr_accessor :test
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@api_version = "23.0"
|
21
|
+
@test = false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Metaforce
|
4
|
+
class Manifest
|
5
|
+
SFDC_API_VERSION = "23.0"
|
6
|
+
|
7
|
+
# example format
|
8
|
+
# {
|
9
|
+
# :apex_class => [
|
10
|
+
# "TestController",
|
11
|
+
# "TestClass"
|
12
|
+
# ],
|
13
|
+
# :apex_component => [
|
14
|
+
# "SiteLogin"
|
15
|
+
# ]
|
16
|
+
# }
|
17
|
+
def initialize(components={})
|
18
|
+
# Map component type => folder
|
19
|
+
if components.is_a?(Hash)
|
20
|
+
@components = components
|
21
|
+
elsif components.is_a?(String)
|
22
|
+
@components = {}
|
23
|
+
self.parse(components)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Adds components to the package
|
28
|
+
def add(type, members=nil)
|
29
|
+
unless members.nil?
|
30
|
+
@components[type] = [] if @components[type].nil?
|
31
|
+
members = [members] if members.is_a?(String)
|
32
|
+
members.each do |member|
|
33
|
+
member = member.gsub(/.*\//, '').gsub(/\..*/, '');
|
34
|
+
@components[type].push(member)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Removes components from the package
|
41
|
+
def remove(type, members=nil)
|
42
|
+
unless members.nil?
|
43
|
+
members = [members] if members.is_a?(String)
|
44
|
+
members.each do |member|
|
45
|
+
member = member.gsub(/.*\//, '').gsub(/\..*/, '');
|
46
|
+
@components[type].delete(member)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
if @components[type].empty?
|
50
|
+
@components.delete(type)
|
51
|
+
end
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Filters the components based on a list of files
|
56
|
+
def only(files)
|
57
|
+
components = @components
|
58
|
+
@components = {}
|
59
|
+
files.each do |file|
|
60
|
+
parts = file.split('/').last(2)
|
61
|
+
folder = parts[0]
|
62
|
+
file = parts[1].gsub(/.*\//, '').gsub(/\..*/, '')
|
63
|
+
components.each_key do |type|
|
64
|
+
if component_folder(type) =~ /#{folder}/i
|
65
|
+
unless components[type].index(file).nil?
|
66
|
+
self.add(type, file);
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the components name
|
75
|
+
def component_name(key)
|
76
|
+
COMPONENT_TYPE_MAP[key][:name]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the components folder
|
80
|
+
def component_folder(key)
|
81
|
+
COMPONENT_TYPE_MAP[key][:folder]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns a key for the component name
|
85
|
+
def component_key(name)
|
86
|
+
COMPONENT_TYPE_MAP.each do |key, component|
|
87
|
+
return key if component[:name] == name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a string containing a package.xml file
|
92
|
+
def to_xml
|
93
|
+
xml_builder = Nokogiri::XML::Builder.new do |xml|
|
94
|
+
xml.Package("xmlns" => "http://soap.sforce.com/2006/04/metadata") {
|
95
|
+
@components.each do |key, members|
|
96
|
+
xml.types {
|
97
|
+
members.each do |member|
|
98
|
+
xml.members member
|
99
|
+
end
|
100
|
+
xml.name component_name(key)
|
101
|
+
}
|
102
|
+
end
|
103
|
+
xml.version SFDC_API_VERSION
|
104
|
+
}
|
105
|
+
end
|
106
|
+
xml_builder.to_xml
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_hash
|
110
|
+
@components
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_package
|
114
|
+
components = []
|
115
|
+
@components.each do |type, members|
|
116
|
+
name = component_name(type)
|
117
|
+
components.push({
|
118
|
+
:members => members,
|
119
|
+
:name => name
|
120
|
+
})
|
121
|
+
end
|
122
|
+
components
|
123
|
+
end
|
124
|
+
|
125
|
+
# Parses a package.xml file
|
126
|
+
def parse(file)
|
127
|
+
document = Nokogiri::XML(file).remove_namespaces!
|
128
|
+
document.xpath('//types').each do |type|
|
129
|
+
name = type.xpath('name').first.content
|
130
|
+
key = component_key(name);
|
131
|
+
type.xpath('members').each do |member|
|
132
|
+
if @components[key].is_a?(Array)
|
133
|
+
@components[key].push(member.content)
|
134
|
+
else
|
135
|
+
@components[key] = [member.content]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
self
|
140
|
+
end
|
141
|
+
|
142
|
+
COMPONENT_TYPE_MAP = {
|
143
|
+
:action_override => {
|
144
|
+
:name => "ActionOverride",
|
145
|
+
:folder => "objects"
|
146
|
+
},
|
147
|
+
:analytics_snapshot => {
|
148
|
+
:name => "AnalyticsSnapshot",
|
149
|
+
:folder => "analyticsnapshots"
|
150
|
+
},
|
151
|
+
:apex_class => {
|
152
|
+
:name => "ApexClass",
|
153
|
+
:folder => "classes"
|
154
|
+
},
|
155
|
+
:article_type => {
|
156
|
+
:name => "ArticleType",
|
157
|
+
:folder => "objects"
|
158
|
+
},
|
159
|
+
:apex_component => {
|
160
|
+
:name => "ApexComponent",
|
161
|
+
:folder => "components"
|
162
|
+
},
|
163
|
+
:apex_page => {
|
164
|
+
:name => "ApexPage",
|
165
|
+
:folder => "pages"
|
166
|
+
},
|
167
|
+
:apex_trigger => {
|
168
|
+
:name => "ApexTrigger",
|
169
|
+
:folder => "triggers"
|
170
|
+
},
|
171
|
+
:business_process => {
|
172
|
+
:name => "BusinessProcess",
|
173
|
+
:folder => "objects"
|
174
|
+
},
|
175
|
+
:custom_application => {
|
176
|
+
:name => "CustomApplication",
|
177
|
+
:folder => "applications"
|
178
|
+
},
|
179
|
+
:custom_field => {
|
180
|
+
:name => "CustomField",
|
181
|
+
:folder => "objects"
|
182
|
+
},
|
183
|
+
:custom_labels => {
|
184
|
+
:name => "CustomLabels",
|
185
|
+
:folder => "labels"
|
186
|
+
},
|
187
|
+
:custom_object => {
|
188
|
+
:name => "CustomObject",
|
189
|
+
:folder => "objects"
|
190
|
+
},
|
191
|
+
:custom_object_translation => {
|
192
|
+
:name => "CustomObjectTranslation",
|
193
|
+
:folder => "objectTranslations"
|
194
|
+
},
|
195
|
+
:custom_page_web_link => {
|
196
|
+
:name => "CustomPageWebLink",
|
197
|
+
:folder => "weblinks"
|
198
|
+
},
|
199
|
+
:custom_site => {
|
200
|
+
:name => "CustomSite",
|
201
|
+
:folder => "sites"
|
202
|
+
},
|
203
|
+
:custom_tab => {
|
204
|
+
:name => "CustomTab",
|
205
|
+
:folder => "tabs"
|
206
|
+
},
|
207
|
+
:dashboard => {
|
208
|
+
:name => "Dashboard",
|
209
|
+
:folder => "dashboards"
|
210
|
+
},
|
211
|
+
:data_category_group => {
|
212
|
+
:name => "DataCategoryGroup",
|
213
|
+
:folder => "datacategorygroups"
|
214
|
+
},
|
215
|
+
:document => {
|
216
|
+
:name => "Document",
|
217
|
+
:folder => "document"
|
218
|
+
},
|
219
|
+
:email_template => {
|
220
|
+
:name => "EmailTemplate",
|
221
|
+
:folder => "email"
|
222
|
+
},
|
223
|
+
:entitlement_template => {
|
224
|
+
:name => "EntitlementTemplate",
|
225
|
+
:folder => "entitlementTemplates"
|
226
|
+
},
|
227
|
+
:field_set => {
|
228
|
+
:name => "FieldSet",
|
229
|
+
:folder => "objects"
|
230
|
+
},
|
231
|
+
:home_page_component => {
|
232
|
+
:name => "HomePageComponent",
|
233
|
+
:folder => "homePageComponents"
|
234
|
+
},
|
235
|
+
:layout => {
|
236
|
+
:name => "Layout",
|
237
|
+
:folder => "layouts"
|
238
|
+
},
|
239
|
+
:letterhead => {
|
240
|
+
:name => "Letterhead",
|
241
|
+
:folder => "letterhead"
|
242
|
+
},
|
243
|
+
:list_view => {
|
244
|
+
:name => "ListView",
|
245
|
+
:folder => "objects"
|
246
|
+
},
|
247
|
+
:named_filter => {
|
248
|
+
:name => "NamedFilter",
|
249
|
+
:folder => "objects"
|
250
|
+
},
|
251
|
+
:permission_set => {
|
252
|
+
:name => "PermissionSet",
|
253
|
+
:folder => "permissionsets"
|
254
|
+
},
|
255
|
+
:portal => {
|
256
|
+
:name => "Portal",
|
257
|
+
:folder => "portals"
|
258
|
+
},
|
259
|
+
:profile => {
|
260
|
+
:name => "Profile",
|
261
|
+
:folder => "profiles"
|
262
|
+
},
|
263
|
+
:record_type => {
|
264
|
+
:name => "RecordType",
|
265
|
+
:folder => "objects"
|
266
|
+
},
|
267
|
+
:remote_site_setting => {
|
268
|
+
:name => "RemoteSiteSetting",
|
269
|
+
:folder => "remoteSiteSettings"
|
270
|
+
},
|
271
|
+
:report => {
|
272
|
+
:name => "Report",
|
273
|
+
:folder => "reports"
|
274
|
+
},
|
275
|
+
:report_type => {
|
276
|
+
:name => "ReportType",
|
277
|
+
:folder => "reportTypes"
|
278
|
+
},
|
279
|
+
:scontroler => {
|
280
|
+
:name => "Scontroler",
|
281
|
+
:folder => "scontrols"
|
282
|
+
},
|
283
|
+
:sharing_reason => {
|
284
|
+
:name => "SharingReason",
|
285
|
+
:folder => "objects"
|
286
|
+
},
|
287
|
+
:sharing_recalculation => {
|
288
|
+
:name => "SharingRecalculation",
|
289
|
+
:folder => "objects"
|
290
|
+
},
|
291
|
+
:static_resource => {
|
292
|
+
:name => "StaticResource",
|
293
|
+
:folder => "staticResources"
|
294
|
+
},
|
295
|
+
:translations => {
|
296
|
+
:name => "Translations",
|
297
|
+
:folder => "translations"
|
298
|
+
},
|
299
|
+
:validation_rule => {
|
300
|
+
:name => "ValidationRule",
|
301
|
+
:folder => "objects"
|
302
|
+
},
|
303
|
+
:weblink => {
|
304
|
+
:name => "Weblink",
|
305
|
+
:folder => "objects"
|
306
|
+
},
|
307
|
+
:workflow => {
|
308
|
+
:name => "Workflow",
|
309
|
+
:folder => "workflows"
|
310
|
+
}
|
311
|
+
}
|
312
|
+
end
|
313
|
+
end
|